也許更好的閱讀體驗
設\(f[i][j][k]\)表示三堆石子分別為\(i,j,k\)個石子時先手必勝還是先手必敗\(1\)為必勝\(0\)為必敗
由於石子的位置沒有影響,所以\(f[i][j][k]=f[i][k][j]=f[j][i][k]=f[j][k][i]=f[k][i][j]=f[k][j][i]\)
當一種狀態可以轉移成先手必敗態時,該狀態是先手必勝態
很明顯,只要轉移到先手必敗態,那麼對面就必敗了
所以我們列舉後繼狀態然後看能不能轉移到先手必敗態,如能即為必勝態,否則就是必敗態
再加點優化什麼的
若\(f[i][j][k]\)是必敗態,那麼\(f[i][j][k+a] (a>0)\)就是必勝態(當然\(a<0\)也都是必敗態,但是對演算法沒什麼用處)
證明,若\(a>0\),先手可以對\(k\)拿走\(a\)個石子就轉移到必敗態
那麼我們先全部賦值為必勝態,然後當我們找到乙個必敗態後即可\(break\)
用乙個f[i][j]表示有沒有兩堆石子數為\(i,j\)的必敗態,如列舉到的石子堆包含了包含了\(i,j\)即可\(break\)
另外,可對包含乙個為\(0\)的資料特殊對待,下面沒有給出**
下面是主要**
int f[303][303];
int g[303][303][303];
memset(f,1,sizeof(f));
f[0][0][0]=0,g[0][0]=1;
for (int i=0;i<=100;++i)
for (int j=i;j<=100;++j)
f[i][k][j]=f[j][i][k]=f[j][k][i]=f[k][i][j]=f[k][j][i]=f[i][j][k];
if (!f[i][j][k])}}
} }
上面的複雜度是\(o(n^4)\),因為去列舉後繼狀態會列舉到非常多的重複狀態,所以我們考慮由必敗態反推必勝態
這樣重複的狀態就大大減少了,複雜度為\(o(n^3)\)多一點
/*******************************
author:morning_glory
lang:c++
created time:2023年06月10日 星期一 09時35分36秒
*******************************/
#include #include #include using namespace std;
const int maxn = 303;
//}cin;
//}}}
int t,x,y,z;
bool f[maxn][maxn][maxn];
inline void update (int a,int b,int c)
int main()
while (t--)
return 0;
}
取石子遊戲
如下 include include intmain k b a temp floor k 1.0 sqrt 5 2.0 if temp a printf 0 n else printf 1 n return 0 一 巴什博奕 bash game 只有一堆n個物品,兩個人輪流從這堆物品中取物,規定每...
取石子遊戲
有兩堆石子,數量任意,可以不同。遊戲開始由兩個人輪流取石子。遊戲規定,每次有兩種不同的取法,一是可以在任意的一堆中取走任意多的石子 二是可以在兩堆中同時取走相同數量的石子。最後把石子全部取完者為勝者。現在給出初始的兩堆石子的數目,如果輪到你先取,假設雙方都採取最好的策略,問最後你是勝者還是敗者。in...
取石子遊戲
取石子遊戲 time limit 1000ms memory limit 10000k total submissions 25176 accepted 7961 description 有兩堆石子,數量任意,可以不同。遊戲開始由兩個人輪流取石子。遊戲規定,每次有兩種不同的取法,一是可以在任意的一堆...