题目传送门(内部题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. Java 从入门到精通随笔1

    1.java中的main方法必须声明为public static void.String args[]是一个字符串类型的数组,是main()方法的参数. 2.基本数据类型Java有8种基本数据类型:数 ...

  2. python-1:正则表达式(基础知识点)

    1.简单匹配: \d  →匹配一个数字 \w →匹配一个数字或字母 \s  →匹配一个空格(包括tab等空白符) .    →匹配任意字符 *   →匹配任意个字符(包括0个) +  →匹配至少一个字 ...

  3. CentOS 7 安装ActiveMQ

    今天给大家介绍一下 CentOS 7 下如何安装ActiveMQ,每个步骤均为亲自己操作后记录.下面我们开始吧. 1.首先进入自己的目录下面,创建并进入 activeMQ 文件夹(mkdir acti ...

  4. Java 类的构造器中this()和super()的困惑

    关于构造器中super的使用,书本上这样写: “super是指向父类的引用,如果构造方法没有显示地调用父类的构造方法,那么编译器会自动为它加上一个默认的super()方法调用.如果父类由没有默认的无参 ...

  5. redis 学习(13)-- BitMap

    BitMap 什么是 BitMap BitMap,即位图,其实也就是 byte 数组,用二进制表示,只有 0 和 1 两个数字. 如图所示: 重要 API 命令 含义 getbit key offse ...

  6. 启动web项目报错:The server time zone value '�й���׼ʱ��' is unrecognized or represents more than one time zone.

    解决: 在application.properties配置文件中的添加标红部分 spring.datasource.url=jdbc:mysql://127.0.0.1:3306/miaosha?se ...

  7. pt-archiver配置自动归档

    Mysql的数据归档通常使用percona的pt-archiver.通过shell脚本加crontab可以应对大多数场景下的数据自动归档. 安装 Percona Toolkit的安装不再赘述,请自行搜 ...

  8. 在java中使用solr7.2.0 新旧版本创建SolrClient对比

    在Java中使用solr 版本7.2.0 solrj已经更新到了7.2.0,新版本solr获取SolrClient的方式也和之前旧版本有所不同 solr6.5开始不推荐直接使用HttpSolrClie ...

  9. XAMPP环境搭建及同类推荐

    一.什么是xampp XAMPP(Apache+MySQL+PHP+PERL)是一个功能强大的建站集成软件包.这个软件包原来的名字是 LAMPP,但是为了避免误解,最新的几个版本就改名为 XAMPP ...

  10. ftp上传下载功能实现

    该程序分为客户端和服务端,目前已经实现以下功能: 1. 多用户同时登陆 2. 用户登陆,加密认证 3. 上传/下载文件,保证文件一致性 4. 传输过程中现实进度条 5. 不同用户家目录不同,且只能访问 ...