题目描述:

数据范围:2<=n,m<=8

题解:

很明显需要状压。但是怎么压不知道,压什么不知道。

然后从条件下手。

条件1要求黑色在一起白色在一起,记录轮廓线很容易做到。

条件2要求不能出现$2*2$的同色方格。我们还需要再记录当前位置的左上角。

所以这道题的轮廓线长这样。

丑图。

我们需要确定一个顺序记录哪几块互相联通。由于轮廓线奇特的形状我决定这样标号。

如果编号相同但是并不互相联通我们可以知道他俩不同颜色。

为了颜色我们决定记录某个块的颜色,这样可以得到所有颜色。

于是这道题表中存的就是$1$号颜色+所有状态。

为了方便调试我用了十进制。

每次调用时都要解压,处理后压缩放回去。

由于第一行和第一列找不到长这样的轮廓线,我们可以搜出第一行所有状态,处理第一列时直接枚举黑色/白色。

接下来就是精彩的特判环节。

(这一部分针对处于中心部位的一干普通点)

以填黑色为例。

如果这里不能填黑:

1.输入要求白色。

2.拐角处已经有三个黑块。

3.要考虑到上图中红块填上后$5$号块就不再与不定颜色相邻,我们不能把$5$号块憋死我们要判断$5$号是否有与之联通的好朋友在轮廓线上。

类似围棋中的气。

如果没有而且$5$号是白的,那么就不能填黑!

等等好像是错的。

如果红块已经到$(n,m-1)$或者是$(n,m)$,而且轮廓线上其他都是黑的,我们可以放黑色。

所以这又是个特判。

4.对于3我们考虑的是上下断开,能否出现左右断开?

当然可能。

但是只能在最后一行出现。

所以统计答案时要填回去看一眼。

真 恶心。

深思熟虑后糊上去的代码:

#include<cstdio>
#include<cstring>
#include<algorithm>
using namespace std;
#define N 15
#define ll long long
int T,n,m,k,a[N][N];
char ch[N][N];
ll bas[N],ans;
struct Map
{
int hed[],cnt[];
struct EG
{
int nxt;
ll to,w;
}e[2][];
void ae(int f,ll t,ll w)
{
e[++cnt[k]][k].to = t;
e[cnt[k]][k].nxt = hed[f];
e[cnt[k]][k].w = w;
hed[f] = cnt[k];
}
void push(ll u,ll w)
{
for(int j=hed[u%];j;j=e[j][k].nxt)
if(e[j][k].to==u)
{
e[j][k].w += w;
return ;
}
ae(u%,u,w);
}
void clear()
{
cnt[k] = ;
memset(hed,,sizeof(hed));
}
}mp;
int col[N],grp[N],tmp[N],las[N];
ll zip()
{
ll ret = ;
for(int i=;i<=m+;i++)ret=*(ret+grp[i]);
return ret+col[];
}
void upz(ll u)
{
memset(tmp,-,sizeof(tmp));
tmp[]=u%;u/=;
for(int i=m+;i>=;i--,u/=)grp[i]=u%;
for(int i=;i<=m+;i++)
if(tmp[grp[i]]==-)tmp[grp[i]]=tmp[grp[i-]]^;
for(int i=;i<=m+;i++)
col[i]=tmp[grp[i]];
}
void shake()//get the express
{
memset(tmp,,sizeof(tmp));
for(int cnt=,i=;i<=m+;i++)
if(!tmp[grp[i]])tmp[grp[i]]=++cnt;
for(int i=;i<=m+;i++)grp[i]=tmp[grp[i]];
}
bool find_friend(int now,int beg,int ens)
{
int cnt = ;
for(int i=beg;i<=ens;i++)
if(grp[i]==now)cnt++;
return cnt>;
}
bool ck1()
{
for(int i=;i<=m;i++)
if(col[i]+a[][i]==)return ;
return ;
}
bool ck2()
{
int cnt = ;
for(int i=;i<=m;i++)
cnt+=(col[i]!=col[i-]);
return cnt<=;
}
int ck3(int c)
{
if(col[m-]==col[m]&&col[m]==col[m+]&&col[m+]==c)return ;
int c0 = col[m],ret=;
for(int i=;i<=m+;i++)las[i]=grp[i];
col[m] = c;grp[m] = m+;
if(col[m-]==c)
{
int kg = grp[m-];
for(int i=;i<=m+;i++)if(grp[i]==kg)grp[i]=m+;
}
if(col[m+]==c)
{
int kg = grp[m+];
for(int i=;i<=m+;i++)if(grp[i]==kg)grp[i]=m+;
}
shake();
for(int i=;i<=m+;i++)if(grp[i]>)ret = ;
for(int i=;i<=m+;i++)grp[i] = las[i];
if(col[m-]==c)
{
int kg = grp[m-];
for(int i=;i<=m+;i++)if(grp[i]==kg)grp[i]=m+;
}
if(col[m+]==c)
{
int kg = grp[m+];
for(int i=;i<=m+;i++)if(grp[i]==kg)grp[i]=m+;
}
shake();
for(int i=;i<=m+;i++)if(grp[i]>)ret = ;
for(int i=;i<=m+;i++)grp[i]=las[i];
col[m] = c0;
return ret;
}
void PushF()
{
for(int i=;i<(<<m);i++)
{
for(int j=;j<=m;j++)col[j]=(i>>(j-))&;
if(!ck1())continue;
if(!ck2())continue;
grp[]=;
for(int j=;j<=m+;j++)if(col[j]==col[j-])grp[j]=grp[j-];else grp[j]=grp[j-]+;
mp.push(zip(),);
}
}
bool check_b(int i,int j)
{
if(a[i][j]==)return ;
if(col[j-]==&&col[j]==&&col[j+]==)return ;
if((i!=n||j!=m)&&(i!=n||j!=m-))
if(col[j+]==&&!find_friend(grp[j+],j+,m+)&&!find_friend(grp[j+],,j-))
return ;
return ;
}
bool check_w(int i,int j)
{
if(a[i][j]==)return ;
if(col[j-]==&&col[j]==&&col[j+]==)return ;
if((i!=n||j!=m)&&(i!=n||j!=m-))
if(col[j+]==&&!find_friend(grp[j+],j+,m+)&&!find_friend(grp[j+],,j-))
return ;
return ;
}
int main()
{
// freopen("tt.in","r",stdin);
scanf("%d",&T);
bas[]=;
for(int i=;i<=;i++)bas[i] = *bas[i-];
while(T--)
{
scanf("%d%d",&n,&m);
for(int i=;i<=n;i++)
{
scanf("%s",ch[i]+);
for(int j=;j<=m;j++)
{
if(ch[i][j]=='o')a[i][j]=;
else if(ch[i][j]=='#')a[i][j]=;
else a[i][j]=;
}
}
ans=,k=,mp.clear();
PushF();
for(int i=;i<=n;i++)
{
k^=;mp.clear();
for(int j=;j<=mp.cnt[!k];j++)
{
ll now = mp.e[j][!k].to,val = mp.e[j][!k].w;
upz(now);
for(int o=m+;o>=;o--)grp[o]=grp[o-],col[o]=col[o-];
for(int q=;q<=m+;q++)las[q]=grp[q];
if(a[i][]!=)//black
{
if(col[]==)
{
col[]=,grp[]=grp[];
shake();
mp.push(zip(),val);
}else
{
if(find_friend(grp[],,m+))
{
col[]=,grp[]=m+;
shake();
mp.push(zip(),val);
}else if(i==n&&m==)
{
col[]=,grp[]=m+;
shake();
mp.push(zip(),val);
}
}
}
for(int q=;q<=m+;q++)grp[q]=las[q];
if(a[i][]!=)//white
{
if(col[]==)
{
col[]=,grp[]=grp[];
shake();
mp.push(zip(),val);
}else
{
if(find_friend(grp[],,m+))
{
col[]=,grp[]=m+;
shake();
mp.push(zip(),val);
}else if(i==n&&m==)
{
col[]=,grp[]=m+;
shake();
mp.push(zip(),val);
}
}
}
}
for(int j=;j<=m;j++)
{
k^=,mp.clear();
for(int o=;o<=mp.cnt[!k];o++)
{
ll now = mp.e[o][!k].to,val = mp.e[o][!k].w;
upz(now);int c0 = col[j];
if(i==n&&j==m)
{
if(n==&&m==)
{
if(col[]==col[])
{
if((a[n][m]==||a[n][m]!=col[])&&col[]==col[])
ans+=val*ck3(col[]^);
else if((a[n][m]==||a[n][m]==col[])&&col[]!=col[])
ans+=val*ck3(col[]);
}else
{
if(a[n][m]==)ans+=val*(ck3()+ck3());
else ans+=val*ck3(a[n][m]);
}
}else
{
if(col[m-]==col[m+])
{
if(a[n][m]==||a[n][m]==col[m-])
ans+=val*ck3(col[m-]);
}else
{
if(a[n][m]==)ans+=val*(ck3()+ck3());
else ans+=val*ck3(a[n][m]);
}
}
continue;
}
if(check_b(i,j))//black
{
col[j]=;grp[j]=m+;
for(int q=;q<=m+;q++)las[q]=grp[q];
if(col[j-]==)
{
int kg = grp[j-];
for(int q=;q<=m+;q++)if(grp[q]==kg)grp[q]=m+;
}
if(col[j+]==)
{
int kg = grp[j+];
for(int q=;q<=m+;q++)if(grp[q]==kg)grp[q]=m+;
}
shake();
if(i==n&&j==m)ans+=val;
mp.push(zip(),val);
for(int q=;q<=m+;q++)grp[q]=las[q];
}
col[j] = c0;
if(check_w(i,j))//white
{
col[j]=;grp[j]=m+;
if(col[j-]==)
{
int kg = grp[j-];
for(int q=;q<=m+;q++)if(grp[q]==kg)grp[q]=m+;
}
if(col[j+]==)
{
int kg = grp[j+];
for(int q=;q<=m+;q++)if(grp[q]==kg)grp[q]=m+;
}
shake();
if(i==n&&j==m)ans+=val;
mp.push(zip(),val);
}
}
}
}
printf("%lld\n",ans);
}
return ;
}

bzoj3336 Uva10572 Black and White的更多相关文章

  1. BZOJ3336: Uva10572 Black and White(插头Dp)

    解题思路: 分类讨论即可. 代码(懒得删Debug了): #include<map> #include<cstdio> #include<vector> #incl ...

  2. bzoj AC倒序

    Search GO 说明:输入题号直接进入相应题目,如需搜索含数字的题目,请在关键词前加单引号 Problem ID Title Source AC Submit Y 1000 A+B Problem ...

  3. imshow() displays a white image for a grey image

    Matlab expects images of type double to be in the 0..1 range and images that are uint8 in the 0..255 ...

  4. ural 2063. Black and White

    2063. Black and White Time limit: 1.0 secondMemory limit: 64 MB Let’s play a game. You are given a r ...

  5. 彩色照片转换为黑白照片(Color image converted to black and white picture)

    This blog will be talking about the color image converted to black and white picture. The project st ...

  6. HDU 5113 Black And White 回溯+剪枝

    题目链接: http://acm.hdu.edu.cn/showproblem.php?pid=5113 Black And White Time Limit: 2000/2000 MS (Java/ ...

  7. SCU3185 Black and white(二分图最大点权独立集)

    题目大概说有几个黑色.白色矩阵,问能选出黑白不相交的矩形面积和的最大值. 建二分图,黑色矩阵为X部的点,白色为Y部,XY的点权都为其矩阵面积,如果有个黑白矩阵相交则它们之间有一条边,那样问题就是要从这 ...

  8. White Rectangles[HDU1510]

    White Rectangles Time Limit: 2000/1000 MS (Java/Others)    Memory Limit: 65536/32768 K (Java/Others) ...

  9. nVIDIA SDK White Paper ----Vertex Texture Fetch Water

    http://blog.csdn.net/soilwork/article/details/713842 nVIDIA SDK White Paper ----Vertex Texture Fetch ...

随机推荐

  1. Codeforces Round #422 (Div. 2) C. Hacker, pack your bags!(更新数组)

    传送门 题意 给出n个区间[l,r]及花费\(cost_i\),找两个区间满足 1.区间和为指定值x 2.花费最小 分析 先用vector记录(l,r,cost)和(r,l,cost),按l排序,再设 ...

  2. HDU5213(容斥定理+莫队算法)

    传送门 题意 给出n个数和幸运数k,m次询问,每次询问[l1,r1]和[l2,r2]有多少对数满足x+y=k,x∈[l1,r1],y∈[l2,r2] 分析 看到m只有3e4,可以考虑\(m\sqrt{ ...

  3. 数位dp真·浅谈 By cellur925

    预警:由于是从$Vergil$学长那里和$Mathison$大神那里学来的,所以清一色记忆化搜索!qwq 巨佬的数位dp讲解(未来的咕咕日报头条): https://www.luogu.org/blo ...

  4. C/C++预处理

    C/C++编译系统编译程序的过程为预处理.编译.链接.预处理器是在程序源文件被编译之前根据预处理指令对程序源文件进行处理的程序.预处理器指令以#号开头标识,末尾不包含分号.预处理命令不是C/C++语言 ...

  5. python之商品操作小程序

    要求:写一个添加商品的程序,商品信息写入txt文件中,以二维字典形式比如:{‘小米’:{‘价格’:‘1999元’,‘数量’:10}} 1.添加商品 #商品名称 #价格 #数量 2.查看商品 3.删除商 ...

  6. LIS && LCS && LCIS && LPS && MCS模板

    1. LIS (Longest Increasing Subsequence) O (n^2): /* LIS(Longest Increasing Subsequence) 最长上升子序列 O (n ...

  7. MVC模式到传统风格的Spring MVC

    现在我们要做个简单的基于servlet的MVC的模型,我们要有一个Product要从表单处获取. MVC中的M是模型,V是视图,C是控制器.视图负责应用的展示,模型封装了数据和业务逻辑,控制器负责接收 ...

  8. 476 Number Complement 数字的补数

    给定一个正整数,输出它的补数.补数是对该数的二进制表示取反.注意:    给定的整数保证在32位带符号整数的范围内.    你可以假定二进制数不包含前导零位.示例 1:输入: 5输出: 2解释: 5的 ...

  9. 数字(number)

    数字(number) Time Limit:2000ms   Memory Limit:128MB 题目描述 LYK定义了一个新的计算. 具体地,一开始它有两个数字a和b. 每一步,它可以将b增加1, ...

  10. LN : leetcode 730 Count Different Palindromic Subsequences

    lc 730 Count Different Palindromic Subsequences 730 Count Different Palindromic Subsequences Given a ...