设为首页 加入收藏

TOP

uva 10561 - Treblecross(Nim)
2015-07-20 17:59:10 来源: 作者: 【 】 浏览:2
Tags:uva 10561 Treblecross Nim

题目链接:uva 10561 - Treblecross

题目大意:n个格子排成一排,其中一些格子有'X',两个游戏者轮流操作,在格子中放X,如果此时出现连续3个X,则获胜。给出先手是否可以取胜,取胜方案的第一步该怎么走。

解题思路:一个X可以导致左右两个的两个格子都不能再放X,因为如果出现XX.、.XX、X.X,那么下一个人肯定胜利。所以对于长度为n的格子序列,g(x)=maxg(x?3),g(x?4)...g(2)XORg(n?7).
所以可以预先处理出g数组,然后对于给定的序列,枚举先手下的位置,判断这种情况下,后手是否为必败态。注意如果先手一步即可胜利要特殊考虑。

 #include 
   
     #include 
    
      #include 
     
       using namespace std; const int maxn = 200; int g[maxn+5], v[maxn+5]; int SG (int s) { memset(v, 0, sizeof(v)); for (int i = 1; i <= s; i++) { int t = 0; if (s - i - 2 >= 0) t ^= g[s-i-2]; if (i - 3 >= 0) t ^= g[i-3]; v[t] = 1; } int mv = -1; while (v[++mv]); return mv; } void init () { memset(g, 0, sizeof(g)); g[1] = g[2] = g[3] = 1; for (int i = 4; i <= 200; i++) g[i] = SG(i); } int n, len, pos[maxn+5]; char str[maxn+5]; bool check () { int pre = -3, ret = 0; for (int i = 0; i <= len; i++) { if (str[i] == 'X') { if (i - pre <= 2) return false; int l = max(i - pre - 5, 0); if (l) ret ^= g[l]; pre = i; } } int l = max(len - pre - 3, 0); if (l) ret ^= g[l]; return ret == 0; } bool judge () { n = 0; len = strlen(str); for (int i = 0; i < len; i++) { if (str[i] == '.') { str[i] = 'X'; if (check()) pos[n++] = i + 1; str[i] = '.'; } if (i && i < len - 1 & str[i-1] == 'X' && str[i+1] == 'X') pos[n++] = i + 1; if (i < len - 2 && str[i+1] == 'X' && str[i+2] == 'X') pos[n++] = i + 1; if (i >= 2 && str[i-1] == 'X' && str[i-2] == 'X') pos[n++] = i + 1; } return n; } int main () { init(); int cas; scanf("%d", &cas); while (cas--) { scanf("%s", str); printf("%s\n", judge() ? "WINNING" : "LOSING"); if (n) printf("%d", pos[0]); for (int i = 1; i < n; i++) printf(" %d", pos[i]); printf("\n"); } return 0; }
     
    
   
】【打印繁体】【投稿】【收藏】 【推荐】【举报】【评论】 【关闭】 【返回顶部
分享到: 
上一篇Codeforce 22B Bargaining Table 下一篇HDU 4911 Inversion(归并求逆序对)

评论

帐  号: 密码: (新用户注册)
验 证 码:
表  情:
内  容: