题目描述:

数据范围: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. Mac下Apache服务器和webDav服务器快速配置

    当自己在家敲代码需要发请求时,就可以配置本地Apache,Mac电脑自带的服务器.这个比windows上的本地服务器还要好用,下面写下最快速配置方案. 0.在开始之前需要给自己的电脑设置下开机密码,想 ...

  2. vue的方法和计算属性的区别

    首先看看 methods 方法 // html <div id="vue"> <button v-on:click = "a++">ad ...

  3. 树的直径初探+Luogu P3629 [APIO2010]巡逻【树的直径】By cellur925

    题目传送门 我们先来介绍一个概念:树的直径. 树的直径:树中最远的两个节点间的距离.(树的最长链)树的直径有两种方法,都是$O(N)$. 第一种:两遍bfs/dfs(这里写的是两遍bfs) 从任意一个 ...

  4. TC学习总结

    带宽管理: TC中规定描述带宽: mbps = 1024 kbps = 1024 * 1024 bps => byte/s mbit = 1024 kbit => kilo bit/s m ...

  5. bzoj 4456 [Zjoi2016]旅行者

    题面 https://www.lydsy.com/JudgeOnline/problem.php?id=4456 题解 分治 设当前work的区间为(x1,y1,x2,y2) 我们将长边分成两半 不妨 ...

  6. [BZOJ5120]无限之环

    Description 曾经有一款流行的游戏,叫做InfinityLoop,先来简单的介绍一下这个游戏: 游戏在一个n×m的网格状棋盘上进行,其中有些小方格中会有水管,水管可能在方格某些方向的边界的中 ...

  7. HBase备份恢复练习

    一.冷备 1.创建测试表并插入测试数据 [root@weekend05 ~]# hbase shell hbase(main):005:0> create 'scores','grade','c ...

  8. C# 部分命名规则

    接触C#开发已经四个月,整理下C#中的命名规则: 一:变量的命名规则(和Java相似) 1.变量名由字母.数字.下划线组成 2.变量名开头只能以字母.下划线开头,不能以数字开头 3.区分大小写 4.命 ...

  9. Java基础50题test4—分解质因数

    [分解质因数] 题目:将一个正整数分解质因数.例如:输入 90,打印出 90=2*3*3*5. 程序分析:对 n 进行分解质因数,应先找到一个最小的质数 k,然后按下述步骤完成: (1)如果这个质数恰 ...

  10. python的与或非运算

    真的很重要,栽了个跟头!!!(虽然以前好像知道...) print(True or False and False) print((True or False) and False) # True # ...