hdu4753 Fishhead’s Little Game 状态压缩,总和一定的博弈

此题和UVA 10891 Game of Sum 总和一定的博弈,区间dp是一个道理,就是预处理麻烦

这是南京网络赛的一题,一直没做,今天做了,虽然时间有点长,但是1ac,这几乎是南京现场赛的最后一道正式题了

typedef long long LL;
const int INF = 1000000007;
const double eps = 1e-10;
const int MAXN = 1000010;
int into[20][20];
int s[12];
vector<int>p[25];
bool vis[1 << 24];
short dp[1 << 24];
/**
0 1 2
3 4 5
6 7 8
9 10 11

12 13 14 15
16 17 18 19
20 21 22 23
*/
short dpf(int ss, int last)
{
    if (!last) return 0;
    if (vis[ss]) return dp[ss];
    vis[ss] = true;
    short &ans = dp[ss];
    ans = 0;
    short tmp = 0;
    short tmplast = last;
    int nextss;

    REP(i, 24)
    {
        if ( (ss & (1 << i)) == 0)
        {
            nextss = ss | (1 << i);
            tmp = 0;
            tmplast = last;
            REP(j, p[i].size())
            {
                if ( (nextss & s[p[i][j]]) == s[p[i][j]] )
                    tmp++, tmplast--;
            }
            tmp += tmplast - dpf(nextss, tmplast);
            ans = max(ans, tmp);
        }
    }
    return ans;
}

void init()
{
    ///点到边的映射
    FE(i, 1, 16)
        if (i % 4) into[i][i + 1] = into[i + 1][i] = i - (i / 4) - 1;
    FE(i, 1, 12)
        into[i][i + 4] = into[i + 4][i] = 12 + i - 1;

    ///边到小正方形的映射,以及小正方形到边的映射
    CLR(s, 0);
    REP(i, 25) p[i].clear();
    REP(i, 9)
    {
        s[i] |= (1 << i);
        p[i].push_back(i);
        s[i] |= (1 << (i + 3));
        p[i + 3].push_back(i);

        s[i] |= (1 << (12 + (i / 3) * 4 + i % 3));
        p[12 + (i / 3) * 4 + i % 3].push_back(i);
        s[i] |= (1 << (13 + (i / 3) * 4 + i % 3));
        p[13 + (i / 3) * 4 + i % 3].push_back(i);
    }
}
int win[2];
int n, m;
int S;

int main ()
{
    int x, y, z;
    int T;
    int nc = 1;
    init();
    RI(T);
    while (T--)
    {
        CLR(win, 0);
        RI(m);
        S = 0;
        REP(i, m)
        {
            RII(x, y);
            z = into[x][y];
            S |= (1 << z);
            REP(j, p[z].size())
            {
                if ((S & s[p[z][j]]) == s[p[z][j]])
                    win[i % 2]++;
            }
        }
        printf("Case #%d: ", nc++);
        int last = 9 - (win[0] + win[1]);
        if (!last)
        {
            puts(win[0] > 4 ? "Tom200" : "Jerry404");
        }
        else
        {
            CLR(vis, 0);
            win[m % 2] += dpf(S, last);
            if (m % 2 == 0) puts(win[m % 2] > 4 ? "Tom200" : "Jerry404");
            else puts(win[m % 2] > 4 ? "Jerry404" : "Tom200");
        }
    }
    return 0;
}


评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值