这是一个比较经典的博弈题目,今年网赛好像是南京赛上有一个类似的题目。
这种题目是没有一定公式或者函数的,需要自己dp或者搜索解决。
题意为分别给你4张写有1,2,3,4,5,6的卡片共24张,每次轮流拿一张卡片,且所有被拿过的卡片的总和不能超过31,谁无法拿出卡片就fail。
首先对于每种卡片一共可能有5中存在情况,所以六张卡片一共有5^6种情况,同时我们保存当前拿到的卡片的数量的和,然后记忆化搜就行了。
记得每次取最优,同时还要注意除掉拿过的牌,当前是谁第一个拿牌哦。
1 #include <iostream> 2 #include <cstdio> 3 #include <cstring> 4 #define maxn 20000 5 using namespace std; 6 7 int dig[7],f[35][maxn];//f[i][j]表示和为i,状态为j的时候是否是必胜状态,如果是的话,值为1,否则值为-1.0表示没有搜过。j用的是5进制,这里比较巧妙。 8 char s[50]; 9 10 int dfs(int tot,int cur) 11 { 12 if (f[tot][cur]!=0) return f[tot][cur]; 13 for (int i=1; i<=6; i++) 14 { 15 if (tot+i>31) continue; 16 if ((cur/dig[i])%5==0) continue; 17 if (dfs(tot+i,cur-dig[i])==-1) 18 { 19 return f[tot][cur]=1; 20 } 21 } 22 return f[tot][cur]=-1; 23 } 24 25 int main() 26 { 27 int ans,cur,tot,tep; 28 dig[1]=1; 29 dig[0]=4; 30 for (int i=2; i<=6; i++) dig[i]=5*dig[i-1],dig[0]+=4*dig[i];//五进制预处理。 31 while (gets(s)) 32 { 33 memset(f,0,sizeof f); 34 cur=dig[0],tot=0; 35 for (int i=0; s[i]; i++) 36 { 37 tep=s[i]-'0'; 38 tot+=tep; 39 cur-=dig[tep]; 40 } 41 if (strlen(s)&1) ans=-1; else ans=1; 42 ans*=dfs(tot,cur); 43 if (ans==-1) printf("%s B ",s); 44 else printf("%s A ",s); 45 } 46 return 0; 47 }