题意:

  n*m的棋盘,每个格子可能是反着的硬币,正着的硬币,没有硬币,每次可以选未选择的一行或者未选择的一列,将这一行/列的硬币取反。如果没有可选的或者硬币已经全部正面,那么游戏结束。

  最后一次操作的选手获得一分,如果最终棋盘上的硬币全是正面,那么双方都获得两分,问先手最多的多少分。

分析:

  双方的最优策略一定是尽量使硬币全是正面,然后在考虑最后一次操作。

  如果局面不可能使硬币全是正面,那么输出(n+m)&1。考虑如何判断。

  如果(i,j)硬币,如果是正面,那么i->j连一条权值为0的边,否则连一条权值为1的。从一个点开始染色,使整张图满足边权等于两个点权的异或值。边权为0表示两个点要么同时选,要么同时不选,为1表示两个点只能选一个。

  如果可以使硬币全是正面,然后对于一个联通块,可能是两种方式涂色,即确定一个点的颜色后,整个联通块也确定了。记录两个方式涂色后1的个数。

  一共有三种可能,两种方式1的个数都是偶数,都是奇数,一个是偶数一个是奇数。那么偶偶与奇奇的没法改变,只有偶奇的根据第一个人选的这个联通块的颜色来确定。

  那么讨论一下即可。

  或者求sg值后异或起来。

代码

#include<cstdio>
#include<algorithm>
#include<iostream>
#include<cstring>
#include<cmath>
#include<cctype>
#include<set>
#include<queue>
#include<vector>
#include<map>
#include<bitset>
using namespace std;
typedef long long LL; inline int read() {
int x=,f=;char ch=getchar();for(;!isdigit(ch);ch=getchar())if(ch=='-')f=-;
for(;isdigit(ch);ch=getchar())x=x*+ch-'';return x*f;
} const int N = ;
int col[N], e[N][N], n, m, c1, c2;
vector<int> T[N];
char s[N][N]; bool dfs(int u) {
col[u] ? c1 ++ : c2 ++;
for (int i = ; i < T[u].size(); ++i) {
int v = T[u][i];
if (col[v] == -) {
col[v] = col[u] ^ e[u][v];
if (dfs(v)) return ;
}
else {
if (col[v] != col[u] ^ e[u][v]) return ;
}
}
return ;
}
void solve() {
n = read(), m = read();
for (int i = ; i <= n; ++i) scanf("%s", s[i] + );
for (int i = ; i <= ; ++i) T[i].clear();
memset(col, -, sizeof(col)); memset(e, , sizeof(e));
for (int i = ; i <= n; ++i)
for (int j = ; j <= m; ++j) {
if (s[i][j] == 'e') continue;
T[i].push_back(j + n); T[j + n].push_back(i);
if (s[i][j] == 'o') e[i][j + n] = e[j + n][i] = ;
else if (s[i][j] == 'x') e[i][j + n] = e[j + n][i] = ;
}
int ans1 = , ans2 = ;
for (int i = ; i <= n + m; ++i) {
if (col[i] == -) {
col[i] = ;
c1 = , c2 = ;
if (dfs(i)) { cout << ((n + m) & ) << "\n"; return ; }
c1 %= , c2 %= ;
if (c1 && c2) ans1 ++;
else if (c1 ^ c2) ans2 ++;
}
}
ans1 %= , ans2 %= ;
if (ans1 | ans2) puts("");
else puts("");
for (int i = ; i <= n + m; ++i) T[i].clear();
}
int main() {
for (int T = read(); T --; solve());
return ;
}

最新文章

  1. Servlet异步上传文件
  2. 20款最佳用户体验的Sublime Text 2/3主题下载及安装方法
  3. [宽度优先搜索] HDU 1372 Knight Moves
  4. IOS单例
  5. 夺命雷公狗—angularjs—16—angularjs里面的缓存
  6. 黄聪:jquery mobile通过a标签页面跳转后,样式丢失、js失效的解决方法
  7. linux服务器修改ftp默认21端口方法
  8. 内存对齐-C语言struct内存占用问题
  9. 路由器WAN口和LAN口详解
  10. CSDN 夏令营课程 项目分析
  11. fiddle2 代理HTTPS请求无效?解决方法。
  12. Centos7:利用crontab定时执行任务
  13. centos 7.5+如何格式化硬盘
  14. .Net Core 中间件之主机地址过滤(HostFiltering)源码解析
  15. React学习及实例开发(一)——开始(转载)
  16. day 52 dom 事件
  17. HDU 2254 奥运(矩阵+二分等比求和)
  18. JavaScript -- Math
  19. 多继承下的super()指向的不一定是直接父类
  20. 三:背包DP

热门文章

  1. 并发容器(四)ConcurrentHashMap 深入解析(JDK1.6)
  2. 如何使用 Swift 开发简单的条形码检测器?
  3. 在Docker Swarm上部署Apache Storm:第2部分
  4. python if 判断
  5. 使用MyEclipse建立working set
  6. 【MySQL 5.7 Reference Manual】15.4.2 Change Buffer(变更缓冲)
  7. INCLUDE COMMON FILES IN HTML USING JQUERY
  8. scp机器间远程拷贝
  9. Python实例---模拟微信网页登录(day2)
  10. 【Alpha 冲刺】 5/12