取球博弈
一开始想到的思路是,搜索所有的对战结果然后将对战结果保存在set中,再通过set来判断先手的输赢。
但是后来发现,这样做忽略了在最聪明的情况下做决策的条件所以这种思路是错的。
// 搜索全部的对战结果,但是忽略了聪明决策的条件
private static void dfs(int n, int me, int you, boolean mark) {
if (n < data[0]) {
f(me, you);// 将对战情况保存
return;
}
if (n >= data[0] && mark == true)
dfs(n - data[0], me + data[0], you, false);
if (n >= data[0] && mark == false)
dfs(n - data[0], me, you + data[0], true);
if (n >= data[1] && mark == true)
dfs(n - data[1], me + data[1], you, false);
if (n >= data[1] && mark == false)
dfs(n - data[1], me, you + data[1], true);
if (n >= data[2] && mark == true)
dfs(n - data[2], me + data[2], you, false);
if (n >= data[2] && mark == false)
dfs(n - data[2], me, you + data[2], true);
}
}
若考虑所谓最聪明情况,就是要考虑决策,我们要对能够下探到的所有局面进行决策。
举个例子:当前局面可以下探到三个规模更小的新局面,则应该按照一定的优先级进行决策来返回一种对战的情况。
- 存在对手输,则直接返回我方胜利
- 不存在对手输,但存在平局,则返回平局
- 否则返回我方失败
private static char dfs2(int n, int player1, int player2, boolean mark) {
// 判断
if (n < data[0]) {
if (mark == true) {
if (player1 % 2 != 0 && player2 % 2 == 0) {
return '+';
} else if (player1 % 2 == 0 && player2 % 2 != 0) {
return '-';
} else {
return '0';
}
} else {
if (player1 % 2 != 0 && player2 % 2 == 0) {
return '-';
} else if (player1 % 2 == 0 && player2 % 2 != 0) {
return '+';
} else {
return '0';
}
}
}
boolean ping = false;
char temp = 'a';
// 尝试下探
for (int i = 0; i < 3; i++) {
if (n < data[i])
continue;
if (mark == true) {
temp = dfs2(n - data[i], player1 + data[i], player2, false);
} else {
temp = dfs2(n - data[i], player1, player2 + data[i], true);
}
if (temp == '-') {// 在最聪明决策下出现了对手输的局面
return '+';
}
if (temp == '0') {
ping = true;
}
}