HDU 4155 (博弈 记忆化搜索)

题目链接:点击这里

题意:有1,2,3,4,5,6各四张牌,AB轮流出牌,谁先使得总和超过31就输.告诉你已经出牌的序列,求最优策略下谁赢.

经典的博弈题了.先把游戏结束的状态挖出来,然后记忆化搜索一遍即可.

#include <bits/stdc++.h>
#define Clear(x,y) memset (x,y,sizeof(x))
#define FOR(a,b,c) for (int a = b; a <= c; a++)
#define REP(a,b,c) for (int a = b; a >= c; a--)
#define fi first
#define se second
#define pii pair<int, int>
#define pli pair<long long, int>
#define pb push_back
#define mod 1000000007
using namespace std;
#define maxn 1005

int dp[5][5][5][5][5][5];//6张牌的状态

void dfs (int x, int y, int z, int a, int b, int c) {
    int num = x+y+z+a+b+c;
    int cnt = 0;//后继状态有多少个1
    int tot = 0;//后继状态总数
    if (x < 4) {
        if (dp[x+1][y][z][a][b][c] == -1) dfs (x+1, y, z, a, b, c);
        cnt += dp[x+1][y][z][a][b][c];
        tot++;
    }
    if (y < 4) {
        if (dp[x][y+1][z][a][b][c] == -1) dfs (x, y+1, z, a, b, c);
        cnt += dp[x][y+1][z][a][b][c];
        tot++;
    }
    if (z < 4) {
        if (dp[x][y][z+1][a][b][c] == -1) dfs (x, y, z+1, a, b, c);
        cnt += dp[x][y][z+1][a][b][c];
        tot++;
    }
    if (a < 4) {
        if (dp[x][y][z][a+1][b][c] == -1) dfs (x, y, z, a+1, b, c);
        cnt += dp[x][y][z][a+1][b][c];
        tot++;
    }
    if (b < 4) {
        if (dp[x][y][z][a][b+1][c] == -1) dfs (x, y, z, a, b+1, c);
        cnt += dp[x][y][z][a][b+1][c];
        tot++;
    }
    if (c < 4) {
        if (dp[x][y][z][a][b][c+1] == -1) dfs (x, y, z, a, b, c+1);
        cnt += dp[x][y][z][a][b][c+1];
        tot++;
    }
    if (num%2 == 0) {//A先手
        if (cnt > 0) dp[x][y][z][a][b][c] = 1;
        else dp[x][y][z][a][b][c] = 0;
    }
    else {//B先手
        if (cnt == tot) dp[x][y][z][a][b][c] = 1;
        else dp[x][y][z][a][b][c] = 0;
    }
}

int main () {
    //freopen ("more.in", "r", stdin);
    memset (dp, -1, sizeof dp);
    for (int x = 0; x <= 4; x++) for (int y = 0; y <= 4; y++) for (int z = 0; z <= 4; z++) {
        for (int a = 0; a <= 4; a++) for (int b = 0; b <= 4; b++) for (int c = 0; c <= 4; c++) {
            int num = x+y+z+a+b+c;
            int sum = x*1+y*2+z*3+a*4+b*5+c*6;
            if (sum > 31) {
                if (num%2 == 0) dp[x][y][z][a][b][c] = 1;
                else dp[x][y][z][a][b][c] = 0;
            }
        }
    }
    dfs (0, 0, 0, 0, 0, 0);
    int tmp[7];
    char s[233];
    while (cin >> s) {
        int n = strlen (s);
        Clear (tmp, 0);
        for (int i = 0; i < n; i++) {
            tmp[s[i]-'0']++;
        }
        int ans = dp[tmp[1]][tmp[2]][tmp[3]][tmp[4]][tmp[5]][tmp[6]];
        printf ("%s %s\n", s, ans ? "A" : "B");
    }
    return 0;
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值