题意:给出一个nm的矩阵,其中有些是固定的黑点/白点,以及一些还未定的点。要求每一个22的矩阵都不会出现全黑/全白的情况。并且所有的黑点处于一个联通块,白点也处于同一个联通块。求最终能有多少种布置空白点的方案,并输出其中一种。
题解:
方便起见,用2个数字来存储一个状态,一个存储连通性,一个存储颜色信息(注:这道题的轮廓线有些不同,并不是在方格边缘,而就是指一排方格)
转移有些麻烦:如果当前颜色和左(L),上(U),左上(LU)相同,即出现了一个全2*2的方格,不合法。
如果当前颜色与U不同,且U为单独联通块,也就意味着U这个联通块会
无法与其他联通块连接,这时候要判定一下,如果还有与U颜色相同,却不在同一个联通块的格子,则不合法(因为无法相连)。如果没有,且当前位置不允许结束这个联通块(即不是最后一行最后两列,只有在这种位置,才允许接下来全部是一种颜色,否则就会出现2*2同色),也不合法。
如果当前颜色与U,L都相同,就会把U和L连在一起。
关于输出方案的问题,和背包问题类似,在每个状态存储一个指向前一个状态的指针(这里的指针并不是严格意义的c++语言中的指针,可以用整型数组来实现),因为尽管无法确定之后状态的合法性,但之前的状态是一定合法的。递归完成后,再从最后一个格子的合法状态开始,沿着指针跳,依次输出每个状态当前格子的颜色即可。
之后就没什么特别的了。
注:代码中LU的颜色存储在第m位
#include<cstdio>
#include<cstring>
#include<algorithm>
#include<queue>
#define SF scanf
#define PF printf
#define MAXNODE 200100
#define MAXN 12
#define MOD 199999
#define update dp[cur^1].push(encode(),cc,dp[cur].f[k],i*m+j,k,c);
using namespace std;
int n,m,ex,ey,cur;
int a[MAXN],num[MAXN],pre[MAXN*MAXN][MAXNODE],op[MAXN*MAXN][MAXNODE];
char mat[MAXN][MAXN];
struct hash{
int sz,adj[MAXNODE],next[MAXNODE];
int state[MAXNODE],f[MAXNODE],col[MAXNODE];
void clr(){
sz=0;
memset(adj,-1,sizeof (adj));
}
void push(int s,int c,int val,int id,int fa,int o){
int u=s%MOD;
for(int i=adj[u];~i;i=next[i])
if(state[i]==s&&col[i]==c){
f[i]+=val;
return ;
}
state[sz]=s;
f[