组合博弈

博弈,一般就是,sg啊,dfs极大极小搜索啊,dp啊,找规律啊....

HDU 1847 Good Luck in CET-4 Everybody!(SG水题)

预处理一下,不然会RE。

HDU 4559 涂色游戏

这个题,非常棒...看了别人的思路,n个1个格子的sg为n%2,我们利用sg函数处理出2*i的值,然后把给出的矩形分段。

#include <cstdio>
#include <cstring>
#include <map>
#include <algorithm>
#include <iostream>
using namespace std;
int dp[5001];
int p[3][5001];
int sg(int x)
{
    int i,l,r;
    int o[5001];
    if(dp[x] >= 0)
    return dp[x];
    memset(o,0,sizeof(o));
    for(i = 1;i <= x;i ++)
    {
        l = i-1;//染1*1的方格
        r = x-i;
        o[sg(l)^sg(r)^1] = 1;
        if(i+1 <= x)//枚举在那里染2*2的方格
        {
            l = i-1;
            r = x-i-1;
            o[sg(l)^sg(r)] = 1;
        }
    }
    for(i = 0;;i ++)
    {
        if(!o[i])
        return dp[x] = i;
    }
    return 0;
}
int main()
{
    int n,m,x,y,i,t,cas = 1,ans,flag;
    memset(dp,-1,sizeof(dp));
    dp[0] = 0;
    dp[1] = 0;
    for(i = 2;i <= 5000;i ++)
    {
        sg(i);
    }
    scanf("%d",&t);
    while(t--)
    {
        memset(p,0,sizeof(p));
        scanf("%d%d",&n,&m);
        for(i = 0;i < m;i ++)
        {
            scanf("%d%d",&x,&y);
            p[x][y] = 1;
        }
        ans = (2*n-m)&1;
        flag = 0;
        for(i = 1;i <= n;i ++)
        {
            if(!p[1][i]&&!p[2][i])
            flag ++;
            else
            {
                ans ^= dp[flag];
                flag = 0;
            }
        }
        ans ^= dp[flag];
        printf("Case %d: ",cas++);
        if(ans)
        printf("Alice\n");
        else
        printf("Bob\n");
    }
    return 0;
}

HDU 1760 A New Tetris Game

极大极小dfs

#include <cstdio>
#include <cstring>
#include <map>
#include <algorithm>
#include <iostream>
using namespace std;
char str[50][50];
int p[50][50];
int n,m;
int dfs()
{
    int i,j,flag;
    flag = 0;
    for(i = 0;i < n-1;i ++)
    {
        for(j = 0;j < m-1;j ++)
        {
            if(p[i][j] == 0&&p[i+1][j] == 0&&p[i][j+1] == 0&&p[i+1][j+1] == 0)
            {
                p[i][j] = p[i+1][j] = p[i][j+1] = p[i+1][j+1] = 1;
                if(dfs() == 0)
                flag = 1;
                p[i][j] = p[i+1][j] = p[i][j+1] = p[i+1][j+1] = 0;
            }
        }
    }
    if(flag)
    return 1;
    else
    return 0;
}
int main()
{
    int i,j;
    while(scanf("%d%d",&n,&m)!=EOF)
    {
        for(i = 0; i < n; i ++)
            scanf("%s",str[i]);
        for(i = 0; i < n; i ++)
        {
            for(j = 0; j < m; j ++)
            {
                if(str[i][j] == ‘0‘)
                p[i][j] = 0;
                else
                p[i][j] = 1;
            }
        }
        if(dfs())
        printf("Yes\n");
        else
        printf("No\n");
    }
    return 0;
}

HDU 3951 Coin Game

这题先不考虑有环的情况,长度为n的sg会比较好求,暴力出sg会发现,除了k = 1之外,其他情况的k,dp[i] >= 1,无论第一步怎么选,肯定是要变化为一段的情况。

搜了一下题解,发现大家直接搞出了 策略,后手可以搞出对称的策略,用sg对不对啊,应该也没问题吧...

#include <cstdio>
#include <cstring>
#include <map>
#include <algorithm>
#include <iostream>
using namespace std;
int dp[1001];
int n;
int sg(int x)
{
    int i,j;
    if(dp[x] >= 0)
    return dp[x];
    int o[1001];
    memset(o,0,sizeof(o));
    for(i = 1;i <= x;i ++)
    {
        for(j = 1;j <= n;j ++)
        {
            if(x-j-(i-1) < 0) continue;
            o[sg(i-1)^sg(x-j-(i-1))] = 1;
        }
    }
    for(i = 0;;i ++)
    if(!o[i])
    return dp[x] = i;
}
int main()
{
    int t,k,cas = 1;
    scanf("%d",&t);
    while(t--)
    {
        scanf("%d%d",&n,&k);
        printf("Case %d: ",cas++);
        if(k == 1)
        {
            if(n%2)
            printf("first\n");
            else
            printf("second\n");
        }
        else
        {
            if(n <= k)
            printf("first\n");
            else
            printf("second\n");
        }
    }
    return 0;
}

组合博弈

时间: 2024-10-05 04:47:41

组合博弈的相关文章

组合博弈入门知识汇总(转)

(一)巴什博奕(Bash Game):只有一堆n个物品,两个人轮流从这堆物品中取物,规 定每次至少取一个,最多取m个.最后取光者得胜. 显然,如果n=m+1,那么由于一次最多只能取m个,所以,无论先取者拿走多少个, 后取者都能够一次拿走剩余的物品,后者取胜.因此我们发现了如何取胜的法则:如果 n=(m+1)r+s,(r为任意自然数,s≤m),那么先取者要拿走s个物品,如果后取者拿走 k(≤m)个,那么先取者再拿走m+1-k个,结果剩下(m+1)(r-1)个,以后保持这样的 取法,那么先取者肯定获

组合博弈入门小结(更新中)

这几天开始学习博弈,发现这一块是个难啃的骨头.以下是我从网上收集的资料汇总: 我国民间有个古老的游戏:就是有物品若干堆,(物品可以是火柴,围棋都可以).两个人轮流从堆中取若干件,规定取光物体者为胜.这个就是我们今天要研究的组合游戏. 组合游戏定义: 1.有且仅有两个玩家    2.游戏双方轮流操作    3.游戏操作状态是个有限的集合(比如:取石子游戏,石子是有限的,棋盘中的棋盘大小的有限的)  4.游戏必须在有限次内结束  5.当一方无法操作时,游戏结束. 现在我们来研究如何取胜: (一)巴什

HDU 5754 Life Winner Bo 组合博弈

Life Winner Bo Problem Description Bo is a "Life Winner".He likes playing chessboard games with his girlfriend G. The size of the chessboard is N×M.The top left corner is numbered(1,1) and the lower right corner is numberd (N,M). For each game,B

组合博弈入门

人生有“三晃”:一晃大了,一晃老了,一晃没了.我晃一下就够了... 以下为网上搜集资料的汇总: 组合游戏定义:        1.有且仅有两个玩家    2.游戏双方轮流操作    3.游戏操作状态是个有限的集合(比如:取石子游戏,石子是有限的,棋盘中的棋盘大小的有限的)  4.游戏必须在有限次内结束  5.当一方无法操作时,游戏结束. (一)巴什博奕(Bash Game):只有一堆n个物品,两个人轮流从这堆物品中取物,规定每次至少取一个,最多取m个.最后取光者得胜.     显然,如果n=m+

组合博弈入门(还没写好)

(1)巴什博奕(Bash Game):只有一堆n个物品,两个人轮流从这堆物品中取物,规定每次至少取一个,最多取m个.最后取光者得胜. (2)威佐夫博奕(Wythoff Game):有两堆各若干个物品,两个人轮流从某一堆或同时从两堆中取同样多的物品,规定每次至少取一个,多者不限,最后取光者得胜. (3)尼姆博奕(Nimm Game):有三堆各若干个物品,两个人轮流从某一堆取任意多的物品,规定每次至少取一个,多者不限,最后取光者得胜. 题目:http://acm.hdu.edu.cn/showpro

【转】ACM博弈知识汇总

博弈知识汇总 转自:http://www.cnblogs.com/kuangbin/archive/2011/08/28/2156426.html 有一种很有意思的游戏,就是有物体若干堆,可以是火柴棍或是围棋子等等均可.两个人轮流从堆中取物体若干,规定最后取光物体者取胜.这是我国民间很古老的一个游戏,别看这游戏极其简单,却蕴含着深刻的数学原理.下面我们来分析一下要如何才能够取胜. (一)巴什博奕(Bash Game):只有一堆n个物品,两个人轮流从这堆物品中取物,规定每次至少取一个,最多取m个.

博弈汇总

转自:http://www.cnblogs.com/kuangbin/archive/2011/08/28/2156426.html 博弈知识汇总 有一种很有意思的游戏,就是有物体若干堆,可以是火柴棍或是围棋子等等均可.两个人轮流从堆中取物体若干,规定最后取光物体者取胜.这是我国民间很古老的一个游戏,别看这游戏极其简单,却蕴含着深刻的数学原理.下面我们来分析一下要如何才能够取胜. (一)巴什博奕(Bash Game):只有一堆n个物品,两个人轮流从这堆物品中取物,规定每次至少取一个,最多取m个.

H - 组合

Description 一年在外 父母时刻牵挂 春节回家 你能做几天好孩子吗 寒假里尝试做做下面的事情吧 陪妈妈逛一次菜场 悄悄给爸爸买个小礼物 主动地 强烈地 要求洗一次碗 某一天早起 给爸妈用心地做回早餐 如果愿意 你还可以和爸妈说 咱们玩个小游戏吧 ACM课上学的呢- 下面是一个二人小游戏:桌子上有M堆扑克牌:每堆牌的数量分别为Ni(i=1…M):两人轮流进行:每走一步可以任意选择一堆并取走其中的任意张牌:桌子上的扑克全部取光,则游戏结束:最后一次取牌的人为胜者. 现在我们不想研究到底先手

[博弈]

http://blog.sina.com.cn/s/blog_83d1d5c70100y9yd.html ----很好的一篇sg函数资料,可惜不是sina用户转载不了. hdu1846(记忆化搜索) #include<cstdio> #include<cstring> #include<algorithm> using namespace std; int cas,n,m; int sg[1010]; int dfs(int x) { if(x<=m)return