【连通性状态压缩DP】UVA10572Black&White

该博客介绍了如何解决UVA10572Black&White问题,这是一个要求矩阵中2x2的子区域不能全黑或全白,并且所有黑点和白点分别属于同一联通块的题目。文章讨论了使用状态压缩动态规划的方法,详细阐述了状态转移规则和非法情况的判断。同时,还提及了递归实现和搜索实现的区别,指出搜索实现通常在时间和内存效率上更优。
摘要由CSDN通过智能技术生成

题意:给出一个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[
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值