题目传送门(内部题135)


输入格式

  第一行包含一个整数$T$,表示数据组数。
  对于每组数据,第一行两个整数$h,w$,表示棋盘大小。
  接下来$h$行,每行一个长度为$w$的字符串,每个位置由为$o,x,e$中一个。如果这个位置为$e$表示没有硬币,如果是$o$表示正面朝上,否则表示反面朝上。


输出格式

  共$T$行,每行一个整数表示小$M$的分数。


样例

样例输入:

1
2 5
exexe
xeoex

样例输出:

3


数据范围与提示

  $10\%$的数据,保证答案都为$0$或$1$。
  $30\%$的数据,保证答案不为$3$。
  另外$30\%$的数据,保证$h,w\leqslant 15$。
  $100\%$的数据,保证$1\leqslant T,h,w\leqslant 100$。


题解

又没有打正解……

首先,答案一定是$0,1,2,3$中的一个。

如果有一种方案能使所有面都朝上,那么答案一定不小于$2$;因为小$M$哪怕要丢掉最后的$1$分也要拿到这$2$分。

如果不能的话答案就只与$h+w$的奇偶性有关了。

那么不妨先来考虑是否可以让正面都朝上。

分为两种情况:

  $\alpha.$正面朝上,那么如果翻转行就要翻转列;如果不翻转行就一定不能翻转列。

  $\beta.$反面朝上,那么如果翻转行就不能翻转列;如果不翻转行就一定要翻转列。

用拓展域并查集维护,看最终态有没有矛盾即可。

再来考虑是否先手必胜。

分为三种情况:

  $\alpha.$如果有一个集合对应偶数次翻转,它的对立集合也对应偶数次翻转,那么不用管它。

  $\beta.$如果有一个集合对应奇数次翻转,它的对立集合也对应奇数次翻转。

  $\gamma.$如果有一个集合对应奇数次翻转,他的对立集合对应偶数次翻转。

所以我们可以只考虑后两种状态。

考虑$DP$,设$dp[i][j]$表示$\beta$状态有$i$个,$\gamma$状态有$j$个是否可行。

初始化$dp[0][0]=0$。

状态转移方程有$3$个:

  $\alpha.dp[i][j]|=!dp[i][j-1]$:选择两个奇数集合,将其变成偶数集合。

  $\beta.dp[i][j]|=!dp[i-1][j]$:选择一个奇偶面集合的奇面,将其变成偶数集合。

  $\gamma.dp[i][j]|=!dp[i-1][j+1]$:选择一个奇偶面集合的偶面,将其变成奇数集合。

这样我们就解决了这道题。

时间复杂度:$\Theta(T\times h\times w)$。

期望得分:$100$分。

实际得分:$100$分。


代码时刻

#include<bits/stdc++.h>
using namespace std;
int h,w;
char ch[101];
int f[401],cnt[401];
bool vis[401],dp[201][401];
void pre_work()
{
memset(vis,0,sizeof(vis));
memset(cnt,0,sizeof(cnt));
memset(dp,0,sizeof(dp));
}
int find(int x){return x==f[x]?x:f[x]=find(f[x]);}
void merge(int x,int y){f[find(x)]=find(y);}
bool check(){for(int i=1;i<=h+w;i++)if(find(i)==find(i+h+w))return 0;return 1;}
int judge()
{
int res1=0,res2=0;
for(int i=1;i<=h+w;i++)cnt[find(i)]++;
for(int i=1;i<=h+w;i++)
{
if(vis[find(i)])continue;
vis[find(i)]=vis[find(i+h+w)]=1;
int flag=0;
if(cnt[find(i)]&1)flag++;
if(cnt[find(i+h+w)]&1)flag++;
if(flag==1)res1++;if(flag==2)res2++;
}
for(int i=1;i<=res1+res2;i++)dp[0][i]=i&1;
for(int i=1;i<=res1;i++)
{
dp[i][0]|=(!dp[i-1][1])|(!dp[i-1][0]);
for(int j=1;j<=res1+res2;j++)
dp[i][j]|=(!dp[i-1][j+1])|(!dp[i-1][j])|(!dp[i][j-1]);
}
return dp[res1][res2];
}
int main()
{
int T;scanf("%d",&T);
while(T--)
{
pre_work();
scanf("%d%d",&h,&w);
for(int i=1;i<=((h+w)<<1);i++)f[i]=i;
for(int i=1;i<=h;i++)
{
scanf("%s",ch+1);
for(int j=1;j<=w;j++)
switch(ch[j])
{
case 'o':
merge(i,j+h);
merge(i+h+w,j+2*h+w);
break;
case 'x':
merge(i,j+2*h+w);
merge(i+h+w,j+h);
break;
}
}
if(check())printf("%d\n",judge()+2);
else printf("%d\n",(h+w)&1);
}
return 0;
}

rp++

[CSP-S模拟测试]:硬币(博弈论+DP+拓展域并查集)的更多相关文章

  1. [CSP-S模拟测试]:Dash Speed(线段树+并查集+LCA)

    题目描述 比特山是比特镇的飙车圣地.在比特山上一共有$n$个广场,编号依次为$1$到$n$,这些广场之间通过$n−1$条双向车道直接或间接地连接在一起,形成了一棵树的结构. 因为每条车道的修建时间以及 ...

  2. 【8.22校内测试】【数学】【并查集】【string】

    今天的t2t3能打出来80分的暴力都好满足啊QwQ.(%%%$idy$ 今天的签到题,做的时候一眼就看出性质叻qwq.大于11的所有数分解合数都可以用4.6.9表示,乱搞搞就可以了. #include ...

  3. POJ1417:True Liars(DP+带权并查集)

    True Liars Time Limit: 2000/1000 MS (Java/Others)    Memory Limit: 32768/32768 K (Java/Others)Total ...

  4. [CSP-S模拟测试]:B(DP+数学)

    题目传送门(内部题45) 输入格式 第一行$3$个整数$n,m,P$.第二行$m$个整数,表示$m$次询问. 输出格式 一行$m$个整数表示答案. 样例 样例输入1: 2 4 40 1 2 3 样例输 ...

  5. [CSP-S模拟测试]:蛇(DP+构造+哈希)

    题目传送门(内部题140) 输入格式 前两行有两个长度相同的字符串,描述林先森花园上的字母. 第三行一个字符串$S$. 输出格式 输出一行一个整数,表示有多少种可能的蛇,对$10^9+7$取模. 样例 ...

  6. [CSP-S模拟测试]:最小值(DP+乱搞)

    题目背景 $Maxtir$更喜欢序列的最小值. 题目传送门(内部题128) 输入格式 第一行输入一个正整数$n$和四个整数$A,B,C,D$. 第二行输入$n$个整数,第$i$个数表示$a_i$. 输 ...

  7. [CSP-S模拟测试]:花(DP)

    题目传送门(内部题111) 输入格式 一个整数$T$,表示测试数据组数. 每组测试数据占一行,两个整数,分别表示$L$和$S$. 输出格式 对每组数据,输出一个整数表示答案. 样例 样例输入1: 13 ...

  8. [CSP-S模拟测试]:计数(DP+记忆化搜索)

    题目描述 既然是萌萌哒$visit\text{_}world$的比赛,那必然会有一道计数题啦!考虑一个$N$个节点的二叉树,它的节点被标上了$1\sim N$的编号.并且,编号为$i$的节点在二叉树的 ...

  9. [CSP-S模拟测试]:matrix(DP)

    题目描述 求出满足以下条件的$n\times m$的$01$矩阵个数:(1)第$i$行第$1~l_i$列恰好有$1$个$1$.(2)第$i$行第$r_i~m$列恰好有$1$个$1$.(3)每列至多有$ ...

随机推荐

  1. MacOS上安装Anaconda+Pycharm+TensorFlow+Keras

    一.安装Anaconda 登录https://www.anaconda.com/download/#macos,下载Anaconda3-5.3.1-MacOSX-x86_64.pkg 二.安装Pych ...

  2. redis集群搭建和哨兵模式以及AOF和RDB持久化

    Redis主从+哨兵模式 1.环境准备 (1)三台独立的linux主机 (2)IP分别为:10.150.200.182 (从) 10.150.200.184(从)  10.150.200.195(主) ...

  3. SQLServer 存储过程详解

    Transact-SQL中的存储过程,非常类似于Java语言中的方法,它可以重复调用.当存储过程执行一次后,可以将语句缓存中,这样下次执行的时候直接使用缓存中的语句.这样就可以提高存储过程的性能. Ø ...

  4. O010、动手实践虚拟网络

    参考https://www.cnblogs.com/CloudMan6/p/5296573.html   本节将演示如何在实验环境中实现下图所示的虚拟网络  

  5. axios+FormData文件上传

    axios+FormData文件上传 原理:FormData上传 创建一个FormData对象,将得到的文件流对象放在FormData内,然后使用axios上传 注意: 1.请求头设置 headers ...

  6. 使用transform属性和animation属性制作跳动的心

    transform属性允许我们对元素进行旋转.缩放.移动和倾斜: animation属性允许我们对元素实现一些动画效果: 跳动的心源码 <!DOCTYPE html> <html l ...

  7. 解决 webpack 打包文件体积过大

    webpack 把我们所有的文件都打包成一个 JS 文件,这样即使你是小项目,打包后的文件也会非常大.下面就来讲下如何从多个方面进行优化. 去除不必要的插件 刚开始用 webpack 的时候,开发环境 ...

  8. 大型分布式爬虫准备 scrapy + request

    那些高手 爬虫好文 而我避免这些问题的方式,控制台清除所有定时 var id = setInterval(function() {}, 0); while (id--) clearInterval(i ...

  9. Go语言的基本语法(二)

    一·if   -else (1) package main import "fmt" // if - else //func main(){ // // 先定义 一个变量 // v ...

  10. 让IE6、IE7、IE8、IE9、IE10、IE11支持Bootstrap的解决方法

    最近做一个Web网站,之前一直觉得bootstrap非常好,这次使用了bootstrap3,在chrome,firefox,safari,opera,360浏览器(极速模式).搜狗浏览器等浏览器下均没 ...