将一个格子看作一个节点,相邻(有公共边)的同色格子之间连边,那么由前两个条件即要求图恰被分为两个非空连通块(由于$n,m\ge 3$,显然不能不使用某种颜色)

下面,来分析图中的简单环,其对应于网格图上即会将网格图分为了两部分,简单分类讨论不难发现只有这个环恰有最外圈所有节点构成时仍能满足第3个条件

换言之,第3个条件即等价于图上至多存在一个所有最外圈节点所构成的环(由于$n,m\ge 3$,显然允许存在)

不妨先强制其不存在环,注意到$nm\le 100$​,不妨假设$n\ge m$​(否则交换),从上到下依次dp,并状压前$m$​​个点的颜色以及连通性,根据没有环即可转移

若仅保留可能得到的状态,最终状态数不超过$2\times 10^{4}$​,即可以通过

关于最外圈所有节点所构成的环,特判最后两个节点的状态即可

(实现上可能有一些细节,可以参考代码)

  1 #include<bits/stdc++.h>
2 using namespace std;
3 #define N 105
4 #define mod 998244353
5 #define ll long long
6 #define fi first
7 #define se second
8 vector<pair<ll,int> >vv,v[2];
9 int t,n,m,ans,a[N][N],c[N],bl[N];
10 ll get_hash(){
11 ll s=0;
12 for(int i=0;i<m;i++)s=((s<<1)|c[i]);
13 for(int i=0;i<m;i++)s=((s<<4)|bl[i]);
14 return s;
15 }
16 void get_val(ll s){
17 for(int i=m-1;i>=0;i--,s>>=4)bl[i]=(s&15);
18 for(int i=m-1;i>=0;i--,s>>=1)c[i]=(s&1);
19 }
20 bool check(){
21 int x=-1,y=-1;
22 for(int i=0;i<m;i++){
23 if (!c[i]){
24 if (x<0)x=bl[i];
25 if (x!=bl[i])return 0;
26 }
27 else{
28 if (y<0)y=bl[i];
29 if (y!=bl[i])return 0;
30 }
31 }
32 return 1;
33 }
34 void merge(int x,int y){
35 if (x>y)swap(x,y);
36 for(int i=0;i<m;i++)
37 if (bl[i]==y)bl[i]=x;
38 }
39 void dfs(int k){
40 if (k==m){
41 v[0].push_back(make_pair(get_hash(),1));
42 return;
43 }
44 if (a[0][k]!=1){
45 c[k]=0,bl[k]=k;
46 if ((k)&&(!c[k-1]))bl[k]=bl[k-1];
47 dfs(k+1);
48 }
49 if (a[0][k]!=0){
50 c[k]=1,bl[k]=k;
51 if ((k)&&(c[k-1]))bl[k]=bl[k-1];
52 dfs(k+1);
53 }
54 }
55 int calc(ll s,int pos,int p){
56 get_val(s);
57 if (c[pos]==p){
58 if (!pos)return 1;
59 if (bl[pos-1]==bl[pos])return 0;
60 if (c[pos-1]==c[pos])merge(bl[pos-1],bl[pos]);
61 return 1;
62 }
63 bool flag=0;
64 for(int i=0;i<m;i++)
65 if ((i!=pos)&&(bl[i]==bl[pos]))flag=1;
66 if (!flag)return 0;
67 c[pos]=p;
68 if (bl[pos]!=pos)bl[pos]=pos;
69 else{
70 for(int i=0;i<m;i++)
71 if ((i!=pos)&&(bl[i]==pos)){
72 for(int j=0;j<m;j++)
73 if ((j!=pos)&&(bl[j]==pos))bl[j]=i;
74 break;
75 }
76 }
77 if ((pos)&&(c[pos-1]==c[pos]))bl[pos]=bl[pos-1];
78 return 1;
79 }
80 int main(){
81 scanf("%d",&t);
82 while (t--){
83 scanf("%d%d",&n,&m);
84 if (n>=m){
85 for(int i=0;i<n;i++)
86 for(int j=0;j<m;j++)scanf("%d",&a[i][j]);
87 }
88 else{
89 for(int i=0;i<n;i++)
90 for(int j=0;j<m;j++)scanf("%d",&a[j][i]);
91 swap(n,m);
92 }
93 int p=ans=0;
94 v[0].clear();
95 dfs(0);
96 for(int i=1;i<n;i++)
97 for(int j=0;j<m;j++){
98 if ((i==n-1)&&(j>=m-2))continue;
99 vv.clear();
100 for(int k=0;k<v[p].size();k++){
101 ll s=v[p][k].fi;
102 if ((a[i][j]!=1)&&(calc(s,j,0)))vv.push_back(make_pair(get_hash(),v[p][k].se));
103 if ((a[i][j]!=0)&&(calc(s,j,1)))vv.push_back(make_pair(get_hash(),v[p][k].se));
104 }
105 sort(vv.begin(),vv.end());
106 p^=1;
107 v[p].clear();
108 for(int k=0;k<vv.size();k++){
109 if ((!k)||(vv[k].fi!=vv[k-1].fi))v[p].push_back(make_pair(vv[k].fi,0));
110 v[p].back().se=(v[p].back().se+vv[k].se)%mod;
111 }
112 }
113 int a1=a[n-1][m-2],a2=a[n-1][m-1];
114 for(int i=0;i<v[p].size();i++){
115 ll s=v[p][i].fi;
116 get_val(s);
117 if (c[m-2]==c[m-1]){
118 if ((c[m-3]==c[m-2])||(!check()))continue;
119 if (a1!=c[m-2]){
120 ans=(ans+v[p][i].se)%mod;
121 if (a2<0)ans=(ans+v[p][i].se)%mod;
122 }
123 continue;
124 }
125 if (c[m-3]==c[m-2]){
126 if (bl[m-3]==bl[m-2]){
127 if ((a1!=c[m-2])&&(a2!=c[m-2])){
128 merge(bl[m-1],bl[m-3]);
129 if (check())ans=(ans+v[p][i].se)%mod;
130 }
131 }
132 else{
133 if (a1!=c[m-1]){
134 merge(bl[m-2],bl[m-3]);
135 if (check()){
136 ans=(ans+v[p][i].se)%mod;
137 if (a2<0)ans=(ans+v[p][i].se)%mod;
138 }
139 }
140 }
141 }
142 else{
143 if (bl[m-3]!=bl[m-1]){
144 if ((a1!=c[m-2])&&(a2!=c[m-2])){
145 merge(bl[m-1],bl[m-3]);
146 if ((check()))ans=(ans+v[p][i].se)%mod;
147 }
148 }
149 else{
150 if (!check())continue;
151 int ss=v[p][i].se;
152 if (a1<0)ss=(ss<<1)%mod;
153 if (a2<0)ss=(ss<<1)%mod;
154 ans=(ans+ss)%mod;
155 if ((a1!=c[m-2])&&(a2!=c[m-1]))ans=(ans-v[p][i].se+mod)%mod;
156 }
157 }
158 }
159 printf("%d\n",ans);
160 }
161 return 0;
162 }

[hdu7065]Yinyang的更多相关文章

  1. css border-radius & yin-yang & taiji

    css border-radius & yin-yang & taiji solution css border-radius & tabs effect https://co ...

  2. [Scheme]Understanding the Yin-Yang Puzzle

    这题目确实比较杀脑细胞... 原题: (let* ((yin ((lambda (cc) (display "@") cc) (call-with-current-continua ...

  3. 【usaco 2013 open yinyang】阴阳

    题目 Farmer John 正在在计划自己的农场漫步.他的农场的结构就像一棵树:农场有N个谷仓(1<= N <=100,000),分别由N-1条路链接.这样,他便可以通过这些谷仓间的道路 ...

  4. CSS代码实例:用CSS代码写出的各种形状图形

    一共收集整理了图形20个,比较实用,同时也为了熟悉CSS的代码.整合了一下,有错误欢迎指出. 1.正方形 #square { width: 100px; height: 100px; backgrou ...

  5. CSS3实现阴阳鱼

    直接上代码: <!doctype html> <html> <head> <meta charset="utf-8" /> < ...

  6. 摘记 史上最强大的40多个纯CSS绘制的图形(一)

    今天在国外的网站上看到了很多看似简单却又非常强大的纯CSS绘制的图形,里面有最简单的矩形.圆形和三角形,也有各种常见的多边形,甚至是阴阳太极和网站小图标,真的非常强大,分享给大家. Square(正方 ...

  7. :before和 :after

    :before和:after的作用就是在指定的元素内容(而不是元素本身)之前或者之后插入一个包含content属性指定内容的行内元素,最基本的用法如下: #example:before { conte ...

  8. 史上最强大的40多个纯CSS绘制的图形

    Square(正方形) #square { width: 100px; height: 100px; background: red; } Rectangle(矩形) #rectangle { wid ...

  9. 40多个纯CSS绘制的图形

    本文由码农网 – 陈少华原创,转载请看清文末的转载要求. 今天在国外的网站上看到了很多看似简单却又非常强大的纯CSS绘制的图形,里面有最简单的矩形.圆形和三角形,也有各种常见的多边形,甚至是阴阳太极和 ...

随机推荐

  1. 将Oracle数据库数据每天备份恢复一次数据到另一台服务器上两份数据

    1.创建用户,授权,创建测试数据 创建用户 CREATE USER test identified by 123; 授权 grant dba to test; 创建测试数据 create table ...

  2. 小白自制Linux开发板 番外篇 一 modprobe加载驱动问题(转载整理)

    使用modprobe加载驱动 转载地址:https://blog.csdn.net/qq_39101111/article/details/78773362 前面我们提到,modprobe并不需要指定 ...

  3. CF468C Hack it! 超详细解答

    CF468C Hack it! 超详细解答 构造+数学推导 原文极简体验 CF468C Hack it! 题目简化: 令\(f(x)\)表示\(x\)在十进制下各位数字之和 给定一整数\(a\)构造\ ...

  4. Go语言核心36讲(Go语言基础知识六)--学习笔记

    06 | 程序实体的那些事儿 (下) 在上一篇文章,我们一直都在围绕着可重名变量,也就是不同代码块中的重名变量,进行了讨论.还记得吗? 最后我强调,如果可重名变量的类型不同,那么就需要引起我们的特别关 ...

  5. spark 解决错误java.io.InvalidClassException

    今天遇到一个现场问题,任务报错java.io.InvalidClassException.在开发环境是没有报错的,正式环境报错.大概类似于下面这样(非报错原文,摘自网上同类博客) java.io.In ...

  6. 【二食堂】Alpha - Scrum Meeting 5

    Scrum Meeting 5 例会时间:4.15 12:30 - 13:00 进度情况 组员 昨日进度 今日任务 李健 1. 主页搭建结束issue2. 与后端协商确定接口的设计3. 查找文本区域功 ...

  7. mybatis自定义分页拦截器

    最近看了一下项目中代码,发现系统中使用的mybatis分页使用的是mybatis自带的分页,即使用RowBounds来进行分页,而这种分页是基于内存分页,即一次查出所有的数据,然后再返回分页需要的数据 ...

  8. 《HelloGitHub》第 67 期

    兴趣是最好的老师,HelloGitHub 让你对编程感兴趣! 简介 分享 GitHub 上有趣.入门级的开源项目. https://github.com/521xueweihan/HelloGitHu ...

  9. Pandas核心用法

    目录 Numpy和Pandas Numpy科学计算 Pandas数据分析 安装jupyter notebook Numpy语法 创建和基本使用 切片索引 布尔索引 对位运算 矩阵的乘除 其他方法 Pa ...

  10. 转:(WIN)S04-CH01 PCIE XDMA开发环境搭建以及环路测试

    摘要: 这一章开始主要介绍 XILINX FPGA PICE IP XDMA IP的使用.XDMA IP使用部分教程分LINUX 篇和WINDOWS篇两个部分.通过实战,面向应用,提供给大家 XILI ...