LightOJ

来源:互联网 发布:旺旺怎么联系淘宝客服 编辑:程序博客网 时间:2024/06/07 19:37

传送门:Treblecross LightOJ - 1229 

题意:一排n个位置,有些位置已经放上了字母X,剩下的是空的。两人轮流放置X在空的位置。放置后出现连续3个X的赢。问先手是否有必胜策略?若有,可以放在哪些地方?

思路:肯定是要枚举先手放的位置,然后判断是否能赢,而判断是否能赢我们就要求sg函数了,然而这个题直接求sg函数的话很难求,因为状态太复杂了,巧妙的思路是将连续的空闲位置拿出来,看成一个独立的nim游戏,求在这些空闲位置上放X的sg值,然后求nim和(异或)就是总状态的sg值了。

详细分析:点击打开链接

代码:

#include<bits/stdc++.h>#define ll long long#define pi acos(-1)#define MAXN 210#define inf 0x3f3f3f3fusing namespace std;typedef pair<int,int>P;char str[MAXN];int len, cnt;int ans[MAXN], sg[MAXN];bool check(){for(int i = 0; i < len - 2; i++)if(str[i] == 'X' && str[i + 1] == 'X' && str[i + 2] == 'X')return 1;return 0;}int get_sg(int n){if(sg[n] != -1) return sg[n];bool vis[MAXN];memset(vis, 0, sizeof(vis));for(int i = 1; i <= n; i++)vis[get_sg(max(i - 3, 0)) ^ get_sg(max(n - i - 2, 0))] = 1;for(int i = 0; i < MAXN; i++)if(!vis[i])return sg[n] = i;}bool judge(){for(int i = 0; i < len; i++){if(str[i] == '.'){str[i] = 'X';if(check()) {str[i] = '.';return 0;}str[i] = '.';}}int num = 0, ans = 0;for(int i = 0; i < len; i++){if(str[i] == 'X' || (i > 0 && str[i - 1] == 'X') || (i > 1 && str[i - 2] == 'X') || (i + 1 < len && str[i + 1] == 'X') || (i + 2 < len && str[i + 2] == 'X')){ans ^= get_sg(num);num = 0;}elsenum++;}ans ^= get_sg(num);return !ans;}void solve(){cnt = 0;for(int i = 0; i < len; i++){if(str[i] == '.'){str[i] = 'X';if(check() || judge())ans[cnt++] = i + 1;str[i] = '.';}}}int main(){int T;cin >> T;int kase = 1;while(T--){memset(sg, -1, sizeof(sg));sg[0] = 0;scanf(" %s", str);len = strlen(str);solve();printf("Case %d:", kase++);if(cnt == 0) printf(" 0");elsefor(int i = 0; i < cnt; i++)printf(" %d", ans[i]);puts("");}    return 0;}


原创粉丝点击