[hdu7065]Yinyang
将一个格子看作一个节点,相邻(有公共边)的同色格子之间连边,那么由前两个条件即要求图恰被分为两个非空连通块(由于$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的更多相关文章
- css border-radius & yin-yang & taiji
css border-radius & yin-yang & taiji solution css border-radius & tabs effect https://co ...
- [Scheme]Understanding the Yin-Yang Puzzle
这题目确实比较杀脑细胞... 原题: (let* ((yin ((lambda (cc) (display "@") cc) (call-with-current-continua ...
- 【usaco 2013 open yinyang】阴阳
题目 Farmer John 正在在计划自己的农场漫步.他的农场的结构就像一棵树:农场有N个谷仓(1<= N <=100,000),分别由N-1条路链接.这样,他便可以通过这些谷仓间的道路 ...
- CSS代码实例:用CSS代码写出的各种形状图形
一共收集整理了图形20个,比较实用,同时也为了熟悉CSS的代码.整合了一下,有错误欢迎指出. 1.正方形 #square { width: 100px; height: 100px; backgrou ...
- CSS3实现阴阳鱼
直接上代码: <!doctype html> <html> <head> <meta charset="utf-8" /> < ...
- 摘记 史上最强大的40多个纯CSS绘制的图形(一)
今天在国外的网站上看到了很多看似简单却又非常强大的纯CSS绘制的图形,里面有最简单的矩形.圆形和三角形,也有各种常见的多边形,甚至是阴阳太极和网站小图标,真的非常强大,分享给大家. Square(正方 ...
- :before和 :after
:before和:after的作用就是在指定的元素内容(而不是元素本身)之前或者之后插入一个包含content属性指定内容的行内元素,最基本的用法如下: #example:before { conte ...
- 史上最强大的40多个纯CSS绘制的图形
Square(正方形) #square { width: 100px; height: 100px; background: red; } Rectangle(矩形) #rectangle { wid ...
- 40多个纯CSS绘制的图形
本文由码农网 – 陈少华原创,转载请看清文末的转载要求. 今天在国外的网站上看到了很多看似简单却又非常强大的纯CSS绘制的图形,里面有最简单的矩形.圆形和三角形,也有各种常见的多边形,甚至是阴阳太极和 ...
随机推荐
- MYSQL小版本升级(5.7.21至5.7.25)
1.环境确认 [root@mysql ~]# ps -ef |grep -i mysql root 9173 1 0 2020 ? 00:00:00 /bin/sh /mysql/data/mysql ...
- Java-爬虫-小项目
爬取数据:(获取请求返回的页面信息,筛选出我们想要的数据就可以了!) 项目地址:https://gitee.com/zwtgit/java-reptile 导入依赖,写一个工具类 <depend ...
- 洛谷3320 SDOI2015寻宝游戏(set+dfs序)(反向迭代器的注意事项!)
被\(STL\)坑害了一个晚上,真的菜的没救了啊. 准确的说是一个叫\(reverse\ iterator\)的东西,就是我们经常用的\(rbegin()\) 有一个非常重要的性质 在反向迭代器中,+ ...
- L1-017 到底有多二 (15 分) java解题
1 import java.util.Scanner; 2 3 public class Main { 4 public static void main(String args[]){ 5 doub ...
- gitk
gitk gitk [<options>] [<revision range>] [--] [<path>-] 查看单个文件的变更历史 gitk -- CppPri ...
- 剑指offer:JZ9 用两个栈实现队列
JZ9 用两个栈实现队列 描述 用两个栈来实现一个队列,使用n个元素来完成 n 次在队列尾部插入整数(push)和n次在队列头部删除整数(pop)的功能. 队列中的元素为int类型.保证操作合法,即保 ...
- elasticsearch基于RBAC认证和集群之间的TLS通讯
elasticsearch基于RBAC认证和集群之间的TLS通讯 一.背景 二.需要解决的问题 三.给es增加用户名和密码访问 1.修改config/elasticsearch.yml 2.访问es集 ...
- Python中根据时间自动创建文件夹
导语 电脑桌面文件太多查找起来比较花费时间,并且凌乱的电脑桌面也会影响工作心情,于是利用python根据时间自动建立当日文件夹,这样就可以把桌面上文件按时间进行存放. 代码实现 # _*_codi ...
- 栈的压入、弹出顺序 牛客网 剑指Offer
栈的压入.弹出顺序 牛客网 剑指Offer 题目描述 输入两个整数序列,第一个序列表示栈的压入顺序,请判断第二个序列是否可能为该栈的弹出顺序.假设压入栈的所有数字均不相等.例如序列1,2,3,4,5是 ...
- 像素反转 牛客网 程序员面试金典 C++ Python
像素反转 牛客网 程序员面试金典 题目描述 有一副由NxN矩阵表示的图像,这里每个像素用一个int表示,请编写一个算法,在不占用额外内存空间的情况下(即不使用缓存矩阵),将图像顺时针旋转90度. 给定 ...