题目大意:

有K堆石子,每堆有Ki个。两人的操作能够是:

            1 从某一堆拿走一个 假设该堆在此之后没有石子了。就消失

            2 合并两个堆

       求是否先手必胜,先手胜输出Alice。否则输出Bob

思路:

这道题读完后毫无头绪。推了半天也推不个所以然来,參看大神代码后,感觉就是一个记忆化搜索啊,唉,知识学多了不会用还是白搭。还得多做题啊!

这里我们把数字分成 1,2,大于等于3的奇数,大于等于4的偶数四类。

       这样分的原因在于。一个大于3的奇数是实际上等价于3的;由于每当对手减一个。自己也减一个。就又变回了一个大于3的奇数。终于变成3。

同理。全部大于2的偶数等价于4。

       所以我们用dp[a][b][c][d]表示有a个1,b个2,c个3,d个4是不是一个必胜态,然后动规求解就好了。

代码:

#include <stdio.h>
#define N 51 bool dp[N][N][N][N] = {0};
bool vis[N][N][N][N] = {0}; int F(int a, int b, int c, int d) // 一个相似记忆化搜索的过程
{
if(!vis[a][b][c][d]){ // 假设后继状态为P状态,则此状态为N状态
if(a >= 1 && !F(a - 1, b, c, d)) dp[a][b][c][d] = 1; // 从 a 中某堆拿走一个。消失
if(b >= 1 && !F(a + 1, b - 1, c, d)) dp[a][b][c][d] = 1; // 从 b 中某堆拿走一个。变成 a
if(c >= 1 && !F(a, b + 1, c - 1, d)) dp[a][b][c][d] = 1; // 从 c 中某堆拿走一个。变成 b
if(d >= 1 && !F(a, b, c + 1, d - 1)) dp[a][b][c][d] = 1; // 从 d 中某堆拿走一个,变成 c if(a >= 2 && !F(a - 2, b + 1, c, d)) dp[a][b][c][d] = 1; // 合并 a 中的两堆,变成 b 类的一堆
if(b >= 2 && !F(a, b - 2, c, d + 1)) dp[a][b][c][d] = 1; // 合并 b 中的两堆,变成 d 类的一堆
if(c >= 2 && !F(a, b, c - 2, d + 1)) dp[a][b][c][d] = 1; // 合并 c 中的两堆,变成 d 类的一堆
if(d >= 2 && !F(a, b, c, d - 2 + 1)) dp[a][b][c][d] = 1; // 合并 d 中的两堆,变成 d 类的一堆 if(a >= 1 && b >= 1 && !F(a - 1, b - 1, c + 1, d)) dp[a][b][c][d] = 1; // 合并 a、b 中的一堆,变成 c 类的一堆
if(a >= 1 && c >= 1 && !F(a - 1, b, c - 1, d + 1)) dp[a][b][c][d] = 1; // 合并 a、c 中的一堆。变成 d 类的一堆
if(a >= 1 && d >= 1 && !F(a - 1, b, c + 1, d - 1)) dp[a][b][c][d] = 1; // 合并 a、d 中的一堆,变成 c 类的一堆
if(b >= 1 && c >= 1 && !F(a, b - 1, c - 1 + 1, d)) dp[a][b][c][d] = 1; // 合并 b、c 中的一堆,变成 c 类的一堆
if(b >= 1 && d >= 1 && !F(a, b - 2, c, d - 1 + 1)) dp[a][b][c][d] = 1; // 合并 b、d 中的一堆。变成 d 类的一堆
if(c >= 1 && d >= 1 && !F(a, b, c - 1 + 1, d - 1)) dp[a][b][c][d] = 1; // 合并 c、d 中的一堆,变成 c 类的一堆 vis[a][b][c][d] = 1;
} return dp[a][b][c][d];
} int main()
{
int loop, n, t, ct = 1;
int a, b, c, d, ans; // a 表示仅仅有一个石子的堆数,b 表示有仅仅有两个石子的堆数。c 表示有奇数个石子的堆数, d 表示有偶数个石子的堆数
scanf("%d", &loop);
while(ct <= loop){
scanf("%d", &n);
a = b = c = d = 0;
for(int i = 0; i < n; i ++){
scanf("%d", &t);
if(t == 1) a ++;
else if(t == 2) b ++;
else if(t % 2 == 1) c ++;
else d ++;
} ans = F(a, b, c, d);
printf("Case #%d: ", ct ++);
if(ans)
printf("Alice\n");
else
printf("Bob\n");
} return 0;
}

2011 ACM-ICPC 成都赛区A题 Alice and Bob (博弈动规)的更多相关文章

  1. 2011 ACM/ICPC 成都赛区(为2013/10/20成都现场赛Fighting)

    hdu 4111  Alice and Bob 博弈:http://www.cnblogs.com/XDJjy/p/3350014.html hdu 4112 Break the Chocolate ...

  2. 2013年山东省第四届ACM大学生程序设计竞赛E题:Alice and Bob

    题目描述 Alice and Bob like playing games very much.Today, they introduce a new game. There is a polynom ...

  3. hdu 4461 第37届ACM/ICPC杭州赛区I题

    题意:给两个人一些棋子,每个棋子有其对应的power,若b没有或者c没有,或者二者都没有,那么他的total power就会减1,total power最少是1,求最后谁能赢 如果b或c出现的话,fl ...

  4. hdu 4460 第37届ACM/ICPC杭州赛区H题 STL+bfs

    题意:一些小伙伴之间有朋友关系,比如a和b是朋友,b和c是朋友,a和c不是朋友,则a和c之间存在朋友链,且大小为2,给出一些关系,求出这些关系中最大的链是多少? 求最短路的最大距离 #include& ...

  5. zoj 3662 第37届ACM/ICPC长春赛区H题(DP)

    题目:给出K个数,使得这K个数的和为N,LCM为M,问有多少种 f[i][j][k]表示选i个数,总和为j,最小公倍数为k memery卡的比较紧,注意不要开太大,按照题目数据开 这种类型的dp也是第 ...

  6. 2017 ACM/ICPC 新疆赛区 I 题 A Possible Tree 带权并查集

    传送门 题意:给定一棵带权树的形态, 但是并不知道每天条边的具体权重. 然后给m个信息, 信息格式为u v val, 表示在树上u 到 v 的路径上经过的边的权重的异或和为val, 问前面最多有多少个 ...

  7. hdu 4462 第37届ACM/ICPC 杭州赛区 J题

    题意:有一块n*n的田,田上有一些点可以放置稻草人,再给出一些稻草人,每个稻草人有其覆盖的距离ri,距离为曼哈顿距离,求要覆盖到所有的格子最少需要放置几个稻草人 由于稻草人数量很少,所以状态压缩枚举, ...

  8. hdu 4463 第37届ACM/ICPC杭州赛区K题 最小生成树

    题意:给坐标系上的一些点,其中有两个点已经连了一条边,求最小生成树的值 将已连接的两点权值置为0,这样一定能加入最小生成树里 最后的结果加上这两点的距离即为所求 #include<cstdio& ...

  9. hdu 4438 第37届ACM/ICPC 天津赛区现场赛H题

    题意:Alice和Bob两个人去打猎,有两种(只)猎物老虎和狼: 杀死老虎得分x,狼得分y: 如果两个人都选择同样的猎物,则Alice得分的概率是p,则Bob得分的概率是(1-p): 但是Alice事 ...

随机推荐

  1. CSS中常用属性之字体属性

    1,以下是CSS中常用字体属性: font-family             字体样式 font-size                字体大小 font-size-adjust  为元素规定 ...

  2. java的回调方式

    经常写js的回调,js的回调很简单,直接传方法名称,但是java中方法不能作为参数传递 但是java中可以传一个对象,在对象中编写多个方法,然后作为参数传递到对象里以后,就可以在适当的时机调用该对象里 ...

  3. 表单文件上传编码方式(enctype 属性)

    enctype 属性规定在发送到服务器之前应该如何对表单数据进行编码. 如下: <form action="upload.php" method="post&quo ...

  4. TabWight

    //修改站号void CDlgParamView::OnPushButton_2_Tab8Clicked(){ // int iSel = m_listStation.GetSelectionMark ...

  5. 工具:docs网页笔记

    用到工具python 网页笔记工具:mkdocs https://www.cnblogs.com/bigmagic/p/10309260.html 案例: https://github.com/zha ...

  6. oracle学习链接

    http://www.cnblogs.com/huyong/category/646939.html

  7. windows mac配置host方法

    配置host方法如下: 1.windows 系统配置host (1)打开电脑的系统盘(一般默认为C盘):C盘 -> Windows -> System32 -> drives -&g ...

  8. 「 Luogu P3137 」X 「 USACO16FEB 」 圆形谷仓

    # 题目大意 管理大大给修下 $\text{Markdown}$ 吧,严重影响做题体验啊. 这道题的意思很简单就是给你一个长度是 $n$ 的环,这个环上不均匀的分布着 $n$ 头奶牛.一头奶牛移动要花 ...

  9. bzoj1174 Toponyms

    给你一个字符集合,你从其中找出一些字符串出来. 希望你找出来的这些字符串的最长公共前缀*字符串的总个数最大化. 第一行给出数字N.N在[2,1000000] 下面N行描述这些字符串,长度不超过2000 ...

  10. 笔试算法题(33):烙饼排序问题 & N!阶乘十进制末尾0的个数二进制最低1的位置

    出题:不同大小烙饼的排序问题:对于N块大小不一的烙饼,上下累在一起,由于一只手托着所有的饼,所以仅有一只手可以翻转饼(假设手足够大可以翻转任意块数的 饼),规定所有的大饼都出现在小饼的下面则说明已经排 ...