CCF201803-4 棋局评估(DFS)

传送门:CCF201803-4 棋局评估

一道暴力搜索。由于两人都以最优策略行棋,故每当轮至1或2时,都对棋盘当前剩余的所有可走位置进行回溯dfs,以得出当前局面的最优结果。又因为1胜时得分为正,2胜时得分为负,故计算最值时,对1使用max,对2使用min。

下面是带注释的代码:

#include <bits/stdc++.h>
#define ll long long
#define INF 0x3f3f3f3f
using namespace std;
int g[4][4];

bool read()
{
    memset(g, 0, sizeof(g));
    bool flag = false;
    for(int i = 1; i <= 3; ++i)
        for(int j = 1; j <= 3; ++j)
        {
            cin >> g[i][j];
            if(g[i][j])
                flag = true;
        }
    return flag;
}

int judge() //返回当前局面的胜者的编号
{
    for(int i = 1; i <= 3; ++i)
    {
        if(g[i][1] != 0 && g[i][1] == g[i][2] && g[i][2] == g[i][3])
            return g[i][1];
        if(g[1][i] != 0 && g[1][i] == g[2][i] && g[2][i] == g[3][i])
            return g[1][i];
    }
    if(g[2][2] != 0 && g[1][1] == g[2][2] && g[2][2] == g[3][3])
        return g[2][2];
    if(g[2][2] != 0 && g[1][3] == g[2][2] && g[2][2] == g[3][1])
        return g[2][2];
    return 0;
}

int dfs(int s) //s记录当前下棋者的编号
{
    int sum = 0, win = judge();
    for(int i = 1; i <= 3; ++i)
        for(int j = 1; j <= 3; ++j)
            if(!g[i][j])
                sum++; //可走位置的数量
    if(win == 1) 
        return sum+1; //1胜,返回1的得分
    if(win == 2)
        return -(sum+1); //2胜,返回2的得分
    if(!sum)         
        return 0; //无位置可走,此时平局,两人得分都为0

    int maxn = -INF, minn = INF;
    for(int i = 1; i <= 3; ++i)
        for(int j = 1; j <= 3; ++j)
            if(!g[i][j])
            {
                g[i][j] = s; //s将棋下在这里
                if(s == 1) //1走完,轮到2下
                    maxn = max(maxn, dfs(2)); //得到最优策略下的得分
                if(s == 2)
                    minn = min(minn, dfs(1));
                g[i][j] = 0; //回溯
            }
    if(s == 1)
        return maxn;
    if(s == 2)
        return minn;
}

void solve()
{
    if(!read())
    {
        cout << 0 << '\n'; //当棋盘为空时,特判
        return;
    }
    else
        cout << dfs(1) << '\n' ; //1先走棋
}

int main()
{
	int t;
	cin >> t;
	while(t--)
            solve();
	return 0;
}

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值