Assignment 5: Combinatorial Games

  • 2234 Matches Game (1)

  • 2484 A Funny Game (2)

  • 3480 John (3)

  • 2505 A multiplication game (3)

  • 1678 I Love this Game! (3)

  • 1704 Georgia and Bob (5)

  • 2960 S-Nim (5)

  • 2232 New Stone-Forfex-Cloth Game (6)

  • 2348 Euclid's Game (6)

  • 1143 Number Game (7)

  • 3317 Stake Your Claim (7)

  • 1740 A New Stone Game (7)


    poj1678

    博弈求差值最大,在最优里取最优

    #include<cstdio>
    #include<algorithm>
    #include<iostream>
    #include<cstring>
    using namespace std;
    #define maxn 10010
    int d[maxn],c[maxn],a[maxn],n,A,B;
    bool dd[maxn],cc[maxn];
    int gaod(int i,int now);
    int gaoc(int i){
       // printf("gaoc i=%d\n",i);
        if(i>=n) return 0;
        if(cc[i]) return c[i];
        int j;
        cc[i]=1;
        for(j=i+1;j<n;++j){
            if(a[j]>=a[i]+A && a[j]<=a[i]+B){
                break;
            }
        }
        if(j>=n) return c[i]=a[i];
       // printf("i=%d j=%d\n",i,j);
        c[i]=a[j]-gaod(j+1,a[j]);
        for(++j;j<n;++j){
            if(a[j]>a[i]+B) break;
            c[i]=max(c[i],a[j]-gaod(j+1,a[j]));
        }
       // printf("di=%d\n",c[i]);
        return c[i]=a[i]-c[i];
    }
    int gaod(int i,int now){
        if(i>=n) return 0;
        if(dd[i]) return d[i];
        int j;
        dd[i]=1;
        for(j=i;j<n;++j){
            if(a[j]>=now+A && a[j]<=now+B){
                break;
            }
        }
        if(j>=n) return d[i]=0;
       // printf("i=%d now=%d aj=%d\n",i,now,a[j]);
        d[i]=gaoc(j);
      //  printf("gaoc [j=%d]=%d\n",j,gaoc(j));
        for(++j;j<n;++j){
            if(a[j]>now+B) break;
            d[i]=max(d[i],gaoc(j));
        }
        return d[i];
    }
    int main(){
       // freopen("test.in","r",stdin);
        int i,t,T,x;
        scanf("%d",&T);
        while(T--){
            scanf("%d%d%d",&t,&A,&B);
            memset(dd,0,sizeof(dd));
            memset(cc,0,sizeof(cc));
            n=0;
            for(i=0;i<t;++i){
                scanf("%d",&x);
                if(x<=0) continue;
                a[n++]=x;
            }
            sort(a,a+n);
            printf("%d\n",gaod(0,0));
          //  printf("gaod2=%d\n",gaod(2,a[1]));
        }
        return 0;
    }

    poj1704

    阶梯博弈,两两一组,考虑偶数位置

    #include<cstdio>
    #include<cstring>
    #include<algorithm>
    #include<iostream>
    using namespace std;
    int a[1010],n;
    int main(){
        int i,s;
        scanf("%*d");
        while(scanf("%d",&n)!=EOF){
            if(n&1){
                a[0]=0;
                for(i=1;i<=n;++i) scanf("%d",&a[i]);
                ++n;
            }else{
                for(i=0;i<n;++i) scanf("%d",&a[i]);
            }
            sort(a,a+n);
            s=0;
            for(i=0;i<n;i+=2){
                s^=(a[i+1]-a[i]-1);
            }
            printf("%s will win\n",s?"Georgia":"Bob");
        }
        return 0;
    }

    poj2348

    博弈中的黄金分割

    #include<cstdio>
    void swap(int &a,int &b){
        int t=a;
        a=b;
        b=t;
    }
    void print(int f){
        printf("%s wins\n",f?"Ollie":"Stan");
    }
    int main(){
        int a,b,f;
        while(scanf("%d%d",&a,&b)!=EOF && a){
            f=0;
            if(a>b) swap(a,b);
            while(1){
                if(b/a>=2 || b%a==0){
                    print(f);
                    break;
                }
                b-=a;
                swap(a,b);
                f=1-f;
            }
        }
        return 0;
    }

    poj3317

    博弈求max-min,用alpha-beta剪枝

    #include<cstdio>
    #include<cstring>
    #include<algorithm>
    #include<queue>
    #include<iostream>
    using namespace std;
    #define inf 0x7fffffff
    char map[10][10];
    int n,cnt,pow3[13],d[60000],x[13],y[13],px,py,ans;
    int gaomax(int state,int dep,int now,int alpha);
    int gaomin(int state,int dep,int now,int beta);
    int vis[10][10],dx[4]={0,0,-1,1},dy[4]={-1,1,0,0};
    typedef pair<int,int> pii;
    queue<pii> q;
    
    int find(char c){
        int i,j,temp,k,xx,yy,tx,ty,a;
        a=0;
        memset(vis,0,sizeof(vis));
        while(!q.empty()) q.pop();
        for(i=0;i<n;++i){
            for(j=0;j<n;++j){
                if(!vis[i][j] && map[i][j]==c){
                    temp=1;
                    vis[i][j]=1;
                    q.push(make_pair(i,j));
                    while(!q.empty()){
                        tx=q.front().first,ty=q.front().second;
                        q.pop();
                        for(k=0;k<4;++k){
                            xx=tx+dx[k],yy=ty+dy[k];
                            if(xx>=0 && xx<n && yy>=0 && yy<n && !vis[xx][yy] && map[xx][yy]==c){
                                vis[xx][yy]=1;
                                q.push(make_pair(xx,yy));
                                ++temp;
                            }
                        }
                    }
                    a=max(temp,a);
                }
            }
        }
        return a;
    }
    int gao(){
        return find('0')-find('1');
    }
    int gaomax(int state,int dep,int now,int alpha){
       // printf("max state=%d\n",state);
        if(d[now]!=-inf) return d[now];
        if(!state) return d[now]=gao();
        int i,j,temp,a=-inf;
        for(i=0;i<cnt;++i){
            if(state&(1<<i)){
                map[x[i]][y[i]]='0';
                temp=gaomin(state^(1<<i),dep+1,now+pow3[i],a);
              //  printf("temp=%d\n",temp);
                map[x[i]][y[i]]='.';
                if(temp>=alpha) return temp;
                a=max(a,temp);
                if(!dep && a>ans){
                    ans=a;
                    px=x[i],py=y[i];
                }
            }
        }
        return d[now]=a;
    }
    int gaomin(int state,int dep,int now,int beta){
       // printf("min state=%d\n",state);
        if(d[now]!=-inf) return d[now];
        if(!state) return d[now]=gao();
        int i,j,temp,a=inf;
        for(i=0;i<cnt;++i){
            if(state&(1<<i)){
                map[x[i]][y[i]]='1';
                temp=gaomax(state^(1<<i),dep+1,now+2*pow3[i],a);
                map[x[i]][y[i]]='.';
                if(temp<=beta) return temp;
                a=min(a,temp);
            }
        }
        return d[now]=a;
    }
    int main(){
       // freopen("test.in","r",stdin);
        int i,j,c0,c1;
        pow3[0]=1;
        for(i=1;i<=10;++i) pow3[i]=pow3[i-1]*3;
        while(scanf("%d",&n)!=EOF && n){
            c0=c1=cnt=0;
            for(i=0;i<n;++i){
                scanf("%s",map[i]);
                for(j=0;j<n;++j){
                    if(map[i][j]=='.'){
                        x[cnt]=i,y[cnt]=j;
                        ++cnt;
                    }else if(map[i][j]=='0'){
                        ++c0;
                    }else{
                        ++c1;
                    }
                }
            }
            if(c0>c1){
                for(i=0;i<n;++i){
                    for(j=0;j<n;++j){
                        if(map[i][j]=='0'){
                            map[i][j]='1';
                        }else if(map[i][j]=='1'){
                            map[i][j]='0';
                        }
                    }
                }
            }
            for(i=0;i<pow3[cnt];++i) d[i]=-inf;
            ans=-inf;
            gaomax((1<<cnt)-1,0,0,inf);
            printf("(%d,%d) %d\n",px,py,ans);
        }
        return 0;
    }

    poj1740

    博弈原则,偶数堆且大小相邻两堆个数都相同为P态,否则为N态。

    #include<cstdio>
    #include<iostream>
    #include<algorithm>
    using namespace std;
    int a[1010];
    int main(){
        int n,i,s,f;
        while(scanf("%d",&n)!=EOF && n){
            for(i=0;i<n;++i) scanf("%d",&a[i]);
            sort(a,a+n);
            for(s=0;s<n;++s){
                if(a[s]) break;
            }
            if((n-s)%2==0){
                f=1;
                for(i=s;i<n;i+=2){
                    if(a[i]!=a[i+1]){
                        f=0;
                        break;
                    }
                }
            }else f=0;
            printf("%d\n",1-f);
        }
        return 0;
    }



  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值