HRBUST - 2320 ——OX(组合博弈问题)

组合博弈博客:https://blog.csdn.net/csdnjiangshan/article/details/79070223

两点结论:

  1. 如果一个状态的后继状态中,存在一个必败态,则该状态为必胜态
  2. 如果一个状态的所有后继状态都为必胜态,则该状态为必败态

思路:这题中还有平态。同理,结合上面的,如果当前状态的后续状态中没有必败态,且有必平态,那么一定是选必平态。

#include<algorithm>
#include<string.h>
#include<stdio.h>
#include<iostream>
#include<map>
using namespace std;
map<int,int>f;
int t,sta,op;
char ch;
int re(int s,int i,int j)//返回第i行第j列的值
{
    int _a=(i-1)*3+j;
    _a=10-_a;
    int y=1;
    for(int i=1;i<_a;i++)
        y*=10;
    s/=y;
    return s%10;
}
int up(int s,int i,int j,int x)//把第i行第j列改为x
{
    int _a=(i-1)*3+j;
    _a=10-_a;
    int y=1,cun;
    for(int i=1;i<_a;i++)
        y*=10;
    cun=s%y;
    s/=(y*10);
    s=s*10;
    s+=x;
    s=s*y+cun;
    return s;
}
int dfs(int x,int s)
{
    if(f[s]) return f[s];
    int pan=x==1?27:3;
    if(re(s,1,1)+re(s,1,2)+re(s,1,3)==pan) return f[s]=2;//判断当前局势
    if(re(s,2,1)+re(s,2,2)+re(s,2,3)==pan) return f[s]=2;
    if(re(s,3,1)+re(s,3,2)+re(s,3,3)==pan) return f[s]=2;
    if(re(s,1,1)+re(s,2,1)+re(s,3,1)==pan) return f[s]=2;
    if(re(s,1,2)+re(s,2,2)+re(s,3,2)==pan) return f[s]=2;
    if(re(s,1,3)+re(s,2,3)+re(s,3,3)==pan) return f[s]=2;
    if(re(s,1,1)+re(s,2,2)+re(s,3,3)==pan) return f[s]=2;
    if(re(s,1,3)+re(s,2,2)+re(s,3,1)==pan) return f[s]=2;
    int cc[15],cut=0,flag=1;
    memset(cc,0,sizeof(cc));
    for(int i=1;i<=3;i++)
    {
        for(int j=1;j<=3;j++)
        {
            if(re(s,i,j)==0)
            {
                cc[++cut]=dfs(x==1?9:1,up(s,i,j,x));
            }
        }
    }
    if(!cut) return f[s]=3;
    for(int i=1;i<=cut;i++)
    {

        if(cc[i]==2)
        {
            return f[s]=1;
        }
        if(cc[i]==3) flag=0;
    }
    if(flag==1) return f[s]=2;
    return f[s]=3;
}
int main()
{
    for(scanf("%d",&t); t; t--)
    {
        f.clear(),sta=0;
        for(int i=1; i<=3; i++)
            for(int j=1; j<=3; j++)
            {
                cin>>ch;
                sta*=10;
                if(ch=='o') sta+=1;//.为0 o为1 x为9
                if(ch=='x') sta+=9;
            }
        cin>>ch;
        op=ch=='o'?1:9;
        dfs(op,sta);//把图转化为九位数10进制来运算
        if(f[sta]==1) printf("%c win!\n",ch);
        if(f[sta]==2) printf("%c win!\n",ch=='o'?'x':'o');
        if(f[sta]==3) printf("tie!\n");
    }
}
/*
2
. . .
. o .
. x .
o
*/

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值