sgu289:Challenging Tic-Tac-Toe(博弈搜索)

题目大意:
       两个人在一个  3×3  的棋盘上分别下  X   0   X   0  后,初始时棋盘为空。如果有  3  个同样的棋子在同一行或同一列或同一斜线,那么游戏结束,该棋子方获胜。
       两个人都会用最佳策略。
       现在给你一个局面,首先判断是否合法 ( 也就是是否可能下得到),然后判断是平局还是  X   0  获胜。

分析:
       差点又被题目意思给坑了。
       就是直接的  SB  博弈搜索,把状态存入  map  中就好了。

AC code:

#include <cstdio>
#include <cmath>
#include <cstdlib>
#include <cstring>
#include <cctype>
#include <algorithm>
#include <string>
#include <sstream>
#include <iostream>
#include <map>
#include <set>
#include <list>
#include <stack>
#include <queue>
#include <vector>
#define pb push_back
#define mp make_pair
#define clr(a, b) memset(a, b, sizeof a)
#define rep(i, a, b) for(int i = (a); i <= (b); ++i)
#define per(i, a, b) for(int i = (a); i >= (b); --i)
typedef long long LL;
typedef double DB;
typedef long double LD;
using namespace std;

void open_init()
{
    #ifndef ONLINE_JUDGE
    freopen("input.txt", "r", stdin);
    freopen("output.txt", "w", stdout);
    #endif
    ios::sync_with_stdio(0);
}

void close_file()
{
    #ifndef ONLINE_JUDGE
    fclose(stdin);
    fclose(stdout);
    #endif
}

enum result {lose,win,draw};

string s[3];
map<vector<int>,result> all;
vector<int> g;

bool WIN(vector<int> now)
{
    int ret = 0;
    rep(i, 0, 2)
        ret += now[i]==now[i+3] && now[i+3]==now[i+6] && now[i];
    rep(i, 0, 2)
        ret += now[i*3]==now[i*3+1] && now[i*3+1]==now[i*3+2] && now[i*3];
    ret += now[0]==now[4] && now[4]==now[8] && now[4];
    ret += now[2]==now[4] && now[4]==now[6] && now[4];
    return ret;
}

int sum0(vector<int> now)
{
    int ret = 0;
    rep(i, 0, 8) ret += !now[i];
    return ret;
}

bool FULL(vector<int> now)
{return !sum0(now);}

result dfs(vector<int> now)
{
    if(all.count(now)) return all[now];
    if(WIN(now)) return all[now] = lose;
    else if(FULL(now)) return all[now] = draw;
    int c1 = 0, c2 = 0, c3 = 0, ch = sum0(now)&1?1:-1;
    rep(i, 0, 8)
        if(!now[i])
        {
            now[i] = ch;
            result tmp = dfs(now);
            if(tmp == lose) c1++;
            else if(tmp == draw) c2++;
            else c3++;
            now[i] = 0;
        }
    if(c1) return all[now] = win;
    else if(c2) return all[now] = draw;
    else return all[now] = lose;
}

int main()
{
    open_init();

    dfs(vector<int>(9, 0));
    while(cin >> s[0])
    {
        g.clear();
        if(s[0] == "Qc") break;
        rep(i, 1, 2) cin >> s[i];
        rep(i, 0, 2)
            rep(j, 0, 2)
                if(s[i][j] == '.') g.pb(0);
                else g.pb(s[i][j]=='X'?1:-1);
        if(!all.count(g)) puts("Illegal position.");
        else 
        {
            result now = all[g];
            if(now == draw) puts("Game is a draw.");
            else printf("%c wins.\n", sum0(g)&1^now==lose?'X':'0');
        }
    }

    close_file();
    return 0;
}

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值