题目传送门(内部题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. zabbix-3.4.6安装

    先安装myql和phpmysql5.7.17: http://www.cnblogs.com/cjsblogs/p/8116782.htmlphp7.2.1: http://www.cnblogs.c ...

  2. (转)Cvte提前批

    1. 加密解密了解么?几种算法,讲一下你了解的(链接) 算法选择:对称加密AES,非对称加密: ECC,消息摘要: MD5,数字签名:DSA 常见加密算法 1.DES(Data Encryption ...

  3. 用git创建仓库关联本地项目,又一直上传不上去

    这个不能勾,我这边勾了用VSCODE上传不了

  4. es分数_score衰减函数

    1.按日期衰变 GET news/doc/_search { "query" : { "function_score": { "query" ...

  5. Maven之私服配置

    一.配置从私服下载 从私服下载主要是将 central 库的下载地址从https://repo1.maven.org/maven2/修改为私服地址,比如http://localhost:8081/re ...

  6. java对象只有值传递,为什么?

    在开始深入讲解之前,有必要纠正一下大家以前的那些错误看法了.如果你有以下想法,那么你有必要好好阅读本文. 错误理解一:值传递和引用传递,区分的条件是传递的内容,如果是个值,就是值传递.如果是个引用,就 ...

  7. SpringBoot 企业级核心技术学习专题

    专题 专题名称 专题描述 001 Spring Boot 核心技术 讲解SpringBoot一些企业级层面的核心组件 002 Spring Boot 核心技术章节源码 Spring Boot 核心技术 ...

  8. python将str类型的数据变成datetime时间类型数据

    如下: import datetime date_str = '2019_05_09' date_date = datetime.date(*map(int, date_str.split('_')) ...

  9. TP5 中的redis 队列

    首先我们看一下自己的TP5的框架中的  TP5\vendor\topthink ,这个文件中有没有think-queue这个文件夹,如果没有请安装, 安装这个是要用到Composer的如果没有安装co ...

  10. 如何在当前目录下打开Windows cmd?

    在当前目录下,按Alt + D (全选当前目录),然后输入 cmd 再按回车 Enter .