一个扑克牌问题

FirstTime 2001-12-31 09:43:20
甲乙2人玩扑克牌游戏,每人手里有1到10共10张牌,出牌是轮流出,但不能出先前出过的牌的约数,谁最后出不下去了,另一方就是赢家。

如果甲先出,双方都采用最合理的走法,哪个必定赢?是什么样的走法?
...全文
179 7 打赏 收藏 转发到动态 举报
写回复
用AI写文章
7 条回复
切换为时间正序
请发表友善的回复…
发表回复
intfree 2002-01-05
  • 打赏
  • 举报
回复
中间避免了重复搜索,
所以你也可以认为这个是动态规划,

其它的部分嘛,就是交互了,不需再解释了吧
intfree 2002-01-05
  • 打赏
  • 举报
回复
先对问题作一个小小的转化:

“不能取拿过的数的约数”,可以看作“把取出的数,以及它的约数都拿走了”。

比如我取10,则你不能取1, 2, 5,等价于我把1, 2, 5, 10都取走
你再取6,则又不能取3,等价于我把1, 2, 3, 6都取走(其中1, 2在上一步取走,不过这也没关系)

我用一个N bits的二进制来表示一个状态,

其中的 take(int now, int i)
就是把 now的二进制所对应的这个状态 取i这个数(和它的约数)

其中的 calc(int can)
就是判断can的二进制所对应的这个状态是否必胜
intfree 2002-01-05
  • 打赏
  • 举报
回复
首先注意到这是一个 博弈 的问题
因此,肯定可以用 博弈树(搜索) 的方法来解。
比如下棋,对于一个状态(棋局),
1. 如果无论我怎么走,我走之后,你都可以取胜,则我必败,
2. 如果存在一个走法,我走之后,你都必败(即下一步无论你如何走,我都必胜),则我必胜

如果没有和局,且不考虑选手失误,则每个状态或者必胜,或者必败。

博弈树就是这样的一个算法,
对于某一些状态,可以直接根据规则,得到它是必胜,还是必败
比如扑克问题,如果没有一张牌,则先走必败。
而对于其它状态,则可以用前面的(1, 2)两条规则,递归的判断是必胜还是必败。

我的这个程序就是基于博弈树算法的。
huang1034 2002-01-05
  • 打赏
  • 举报
回复
intfree()能够列出你的算法?或者加一些注释!
我很希望你解释一下!
mathe 2002-01-03
  • 打赏
  • 举报
回复
既然intfree的回答,想必不会错,先MARK一下,以后有空再看
FirstTime 2002-01-02
  • 打赏
  • 举报
回复
谢谢,但是没看明白,哪个给解释一下?
intfree 2001-12-31
  • 打赏
  • 举报
回复
10张牌,先走必胜,
怎么,不信?那就跟我的程序玩玩吧 :)


#include <iostream.h>
#include <string.h>
#include <conio.h>

const int N = 10;
const int UNKNOW = 2;
const int TRUE = 1;
const int FALSE = 0;

char win[1 << N], choose[1 << N];

int take(int &now, int p)
{

if ((p < 1) || (p > N))
{
return FALSE;
}

int mask = 1 << (p - 1);
if ((now & mask) != 0)
{
now -= mask;
for (int k = 1; k <= p; k ++)
{
if ((p % k) == 0)
{
take(now, k);
}
}
return TRUE;
}
return FALSE;

}

int calc(int can)
{
if (win[can] == UNKNOW)
{
win[can] = FALSE;
for (int i = 1; i <= N; i ++)
{
int x = can;
if (take(x, i))
{
if (!calc(x))
{
choose[can] = i;
win[can] = TRUE;
break;
}
}
}
}
return win[can];
}

void main()
{
memset(win, UNKNOW, sizeof(win));
cout << "N = " << N << endl;
int now = (1 << N) - 1;
do
{
if (calc(now))
{
cout << "computer take " << (int) choose[now] << endl;
take(now, choose[now]);
}
if (!calc(now))
{
int choose;
do
{
cout << "It's your turn: ";
if (now == 0)
{
cout << "Fail" << endl;
cout << endl;
cout << "Press any key to continue ... " << endl;
getch();
break;
}
cin >> choose;
} while (!take(now, choose));
}
} while (now != 0);
}

33,028

社区成员

发帖
与我相关
我的任务
社区描述
数据结构与算法相关内容讨论专区
社区管理员
  • 数据结构与算法社区
加入社区
  • 近7日
  • 近30日
  • 至今
社区公告
暂无公告

试试用AI创作助手写篇文章吧