BZOJ3336: Uva10572 Black and White(插头Dp)
解题思路:
分类讨论即可。
代码(懒得删Debug了):
#include<map>
#include<cstdio>
#include<vector>
#include<cstring>
#include<algorithm>
#define black '#'
#define white 'o'
#define BLACK_AND_WHITE int main(){/*freopen("a.in","r",stdin);*/scanf("%d",&T);while(T--)Black_and_White();return 0;}
typedef long long lnt;
typedef unsigned int uit;
typedef unsigned long long unt;
int T;
int n,m;
int p,q;
unt ans=;
int mp[][];
char cmd[];
uit code[];
uit tod[];
int clor[];
bool col[];
std::map<unt,unt>dp[],ooo;
void minpress(uit *cd)
{
int cnt=;
memset(clor,,sizeof(clor));
for(int i=;i<=m;i++)
{
if(!clor[cd[i]])
clor[cd[i]]=++cnt;
cd[i]=clor[cd[i]];
}
return ;
}
unt compress(uit *cd,int hc)
{
unt ret=hc;
minpress(cd);
for(int i=;i<=m;i++)
ret=ret*10ull+cd[i];
return ret;
}
void decompress(uit *cd,bool *cl,unt sit)
{
for(int i=m;i>=;i--)
{
cd[i]=sit%10ull;
sit/=10ull;
}
cl[]=sit;
for(int i=;i<=m;i++)
if(cd[i]!=cd[i-])
cl[i]=-cl[i-];
else
cl[i]=cl[i-];
return ;
}
bool banned(int l,int r,int pos,uit *cd)
{
for(int i=;i<l;i++)
if(cd[i]==cd[pos-])
return false;
for(int i=r-;i<=m;i++)
if(cd[i]==cd[pos-])
return false;
return true;
}
void update(int cmd,unt tmp,unt v)
{
if(dp[cmd].find(tmp)==dp[cmd].end())
dp[cmd][tmp]=v;
else
dp[cmd][tmp]+=v;
return ;
}
void Insert(int ii,int jj,unt s,unt v,bool b)
{
decompress(code,col,s);
int lu,uu,ll,hc=col[];
/* printf("%d ",hc);
for(int k=0;k<=m;k++)
printf("%d ",code[k]);
printf("%d",v);
/* puts("");/*
for(int i=0;i<=m;i++)
printf("%d ",col[i]);*/
uu=col[jj]^b;
lu=col[jj-]^b;
ll=col[jj-]^b;
/* printf(uu?"b":"w");
printf(lu?"b":"w");
printf(ll?"b":"w");*/
// puts("");
uit maxs=;
for(int i=;i<=m;i++)
maxs=std::max(maxs,code[i]);
for(int i=;i<=m;i++)
tod[i]=code[i];
if(ll)
{
if(lu)
{
if(uu)
tod[jj-]=maxs+;
else
tod[jj-]=tod[jj];
}else{
if(uu)
{
if(ii==n&&jj==m)
return ;
if(banned(jj-,jj+,jj+,tod))
return ;
//printf("+1\n");
tod[jj-]=maxs+;
}else
tod[jj-]=tod[jj];
}
}else{
if(lu)
{
if(uu)
{
if(banned(jj-,jj+,jj+,tod))
{
if(ii!=n||(jj!=m&&jj!=m-))return ;
for(int i=;i<jj-;i++)
if(col[i]==col[jj])
return ;
for(int i=jj+;i<=m;i++)
if(col[i]==col[jj])
return ;
}
tod[jj-]=tod[jj-];
}else{
tod[jj]=tod[jj-]=tod[jj-];
for(int i=;i<=m;i++)
{
if(code[i]==code[jj]||code[i]==code[jj-])
tod[i]=tod[jj-];
}
}
}else{
if(uu)
{
if(banned(jj-,jj+,jj+,tod))
{
if(ii!=n||(jj!=m&&jj!=m-))return ;
for(int i=;i<jj-;i++)
if(col[i]==col[jj])
return ;
for(int i=jj+;i<=m;i++)
if(col[i]==col[jj])
return ;
}
tod[jj-]=tod[jj-];
}else return ;
}
}
unt tmp=compress(tod,hc);
if(ii==n&&jj==m)
{
int cnt=;
decompress(code,col,tmp);
memset(clor,,sizeof(clor));
for(int i=;i<=m;i++)
if(!clor[code[i]])
clor[code[i]]=++cnt;
if(cnt<=)
ans+=v;
return ;
}
update(p,tmp,v);
return ;
}
void Insert(int i,unt s,unt v,bool b)
{
decompress(code,col,s);
int uu,hc=col[];
/* printf("%d ",hc);
for(int k=0;k<=m;k++)
printf("%d ",code[k]);
printf("%d ",v);
puts("");*/
for(int i=;i<=m;i++)
tod[i]=code[i];
uu=col[]^b;
if(uu)
{
if(banned(,,,tod))
return ;
code[]=;
hc=b;
}else
code[]=code[];
unt tmp=compress(code,hc);
if(i==n&&m==)
{
int cnt=;
decompress(code,col,tmp);
memset(clor,,sizeof(clor));
for(int ii=;ii<=m;ii++)
if(!clor[code[ii]])
clor[code[ii]]=++cnt;
if(cnt<=)
ans+=v;
}
update(p,tmp,v);
return ;
}
unt move(unt x)
{
decompress(code,col,x);
int hc=col[];
for(int i=m;i;i--)
code[i]=code[i-];
return compress(code,hc);
}
void Move(void)
{
ooo.clear();
for(std::map<unt,unt>::iterator i=dp[p].begin();i!=dp[p].end();i++)
ooo[i->first]=i->second;
dp[p].clear();
for(std::map<unt,unt>::iterator i=ooo.begin();i!=ooo.end();i++)
{
update(p,move(i->first),i->second);
// printf("%I64u %I64u\n",move(i->first),i->second);
}
return ;
}
void Black_and_White(void)
{
dp[].clear();
dp[].clear();
ans=;
p=,q=;
memset(mp,,sizeof(mp));
memset(code,,sizeof(code));
memset(clor,,sizeof(clor));
scanf("%d%d",&n,&m);
for(int i=;i<=n;i++)
{
scanf("%s",cmd+);
for(int j=;j<=m;j++)
{
if(cmd[j]==white)
mp[i][j]=-;
else if(cmd[j]==black)
mp[i][j]=;
else
mp[i][j]=;
}
}
if(n==&&m==)
{
if(mp[][])
puts("");
else
puts("");
return ;
}
for(int i=;i<(<<m);i++)
{
int cnt=;
code[]=code[]=;
bool ban=false;
for(int j=;j<=m;j++)
{
if(mp[][j]==&&((i&(<<(j-)))==))ban=true;
if(mp[][j]==-&&(i&(<<(j-)))) ban=true;
if(ban)break;
}
if(ban)
continue;
for(int j=;j<=m;j++)
{
if((bool)(i&(<<(j-)))^(bool)(i&(<<(j-))))
cnt++;
code[j]=cnt;
}
int co=i&;
// printf("%d ",co);
// puts("");
unt s=compress(code,co);
// printf("%d\n",s);
update(p,s,);
}
for(int i=;i<=n;i++)
{
// puts("\n~~~~~~~~~~~~~~~~~~~~~~");
std::swap(p,q);
dp[p].clear();
for(std::map<unt,unt>::iterator k=dp[q].begin();k!=dp[q].end();k++)
{
unt s=k->first;
unt v=k->second;
if(mp[i][]!=)
Insert(i,s,v,);
if(mp[i][]!=-)
Insert(i,s,v,);
}
// puts("_________________________");
for(int j=;j<=m;j++)
{
// puts("\n~~~~~~~~~~~~~~~~~~~~~~");
std::swap(p,q);
dp[p].clear();
for(std::map<unt,unt>::iterator k=dp[q].begin();k!=dp[q].end();k++)
{
unt s=k->first;
unt v=k->second;
if(mp[i][j]!=)
Insert(i,j,s,v,);
if(mp[i][j]!=-)
Insert(i,j,s,v,);
}
// puts("_________________________");
}
// puts("%d");
Move();
}
printf("%llu\n",ans);
return ;
}BLACK_AND_WHITE
BZOJ3336: Uva10572 Black and White(插头Dp)的更多相关文章
- BZOJ 3336 Black and White (插头DP)
题目大意: 给你一个n×m的网格,有一些格子已经被涂上了白色或者黑色,让你用黑色或白色填剩下的格子,且填好的网格必须保证: 1.对于任意2×2的子矩阵的4个格子,它们的颜色不能都相同 2.所有黑色的块 ...
- bzoj3336 Uva10572 Black and White
题目描述: 数据范围:2<=n,m<=8 题解: 很明显需要状压.但是怎么压不知道,压什么不知道. 然后从条件下手. 条件1要求黑色在一起白色在一起,记录轮廓线很容易做到. 条件2要求不能 ...
- 插头dp练习
最近学了插头dp,准备陆续更新插头dp类练习. 学习论文还是cdq那篇<基于连通性状态压缩的动态规划问题>. 基本的想法都讲得很通透了,接下来就靠自己yy了. 还有感谢kuangbin大大 ...
- 插头dp
插头dp 感受: 我觉得重点是理解,算法并不是直接想出怎样由一种方案变成另一种方案.而是方案本来就在那里,我们只是枚举状态统计了答案. 看看cdq的讲义什么的,一开始可能觉得状态很多,但其实灰常简单 ...
- HDU 4113 Construct the Great Wall(插头dp)
好久没做插头dp的样子,一开始以为这题是插头,状压,插头,状压,插头,状压,插头,状压,无限对又错. 昨天看到的这题. 百度之后发现没有人发题解,hust也没,hdu也没discuss...在acm- ...
- HDU 4949 Light(插头dp、位运算)
比赛的时候没看题,赛后看题觉得比赛看到应该可以敲的,敲了之后发现还真就会卡题.. 因为写完之后,无限TLE... 直到后来用位运算代替了我插头dp常用的decode.encode.shift三个函数以 ...
- 插头DP专题
建议入门的人先看cd琦的<基于连通性状态压缩的动态规划问题>.事半功倍. 插头DP其实是比较久以前听说的一个东西,当初是水了几道水题,最近打算温习一下,顺便看下能否入门之类. 插头DP建议 ...
- HDU 1693 Eat the Trees(插头DP、棋盘哈密顿回路数)+ URAL 1519 Formula 1(插头DP、棋盘哈密顿单回路数)
插头DP基础题的样子...输入N,M<=11,以及N*M的01矩阵,0(1)表示有(无)障碍物.输出哈密顿回路(可以多回路)方案数... 看了个ppt,画了下图...感觉还是挺有效的... 参考 ...
- HDU 1693 Eat the Trees(插头DP)
题目链接 USACO 第6章,第一题是一个插头DP,无奈啊.从头看起,看了好久的陈丹琦的论文,表示木看懂... 大体知道思路之后,还是无法实现代码.. 此题是插头DP最最简单的一个,在一个n*m的棋盘 ...
随机推荐
- 修复linux的grub2引导(单独/boot,lvm-root)
root@ubuntu:/home/ubuntu# pwd /home/ubuntu root@ubuntu:/home/ubuntu# lsblk NAME MAJ ...
- dmesg---检查和控制内核的环形缓冲区
dmesg命令被用于检查和控制内核的环形缓冲区.kernel会将开机信息存储在ring buffer中.您若是开机时来不及查看信息,可利用dmesg来查看.开机信息保存在/var/log/dmesg文 ...
- GenIcam标准(五)
2.8.10.Enumeration, EnumEntry Enumeration节点把一个名称(name)映射到一个索引值(index value),并实现Ienumeration接口.Enumer ...
- poj1062 Bellman 最短路应用
昂贵的聘礼 Time Limit: 1000MS Memory Limit: 10000K Total Submissions: 41066 Accepted: 11959 Descripti ...
- Android Support Library 23.2用法简析
写在前面的几句话 前几天谷歌发布了android-support-library-23.2支持库,这一次23.2版本增加了一些新的支持库以及新的功能.接下来这篇文章,就是对这些新功能部分做简单的用法介 ...
- 关键字&标识符
关键字:被Java语言赋予了特殊含义,用做专门用途的字符串(单词) 保留字: 标识符:凡是自己可以起名字的地方都叫标识符 命名的规则:(一定要遵守,不遵守就会报编译的错误)由26个英文字母大小写,0- ...
- vSphere5安装配置视频教程
vSphere5安装配置视频教程 本文出自 "李晨光原创技术博客" 博客,请务必保留此出处http://chenguang.blog.51cto.com/350944/819550
- AtCoderAGC003D Anticube
Description: 给定一个序列\(a\),要求选出最多的序列元素并保证两两元素的乘积不为立方数 Solution: 我们考虑哪些因子是有用的,如果一个因子的指数\(>3\),我们可以将他 ...
- 学习参考《Python数据分析与挖掘实战(张良均等)》中文PDF+源代码
学习Python的主要语法后,想利用python进行数据分析,感觉<Python数据分析与挖掘实战>可以用来学习参考,理论联系实际,能够操作数据进行验证,基础理论的内容对于新手而言还是挺有 ...
- 【Linux系统引导过程】
*** 第一步 开机自检 根据主板BIOS中的启动顺序,移交系统控制权. 当你打开计算机电源,计算机会首先加载BIOS信息,BIOS信息是如此的重要,以至于计算机必须在最开始就找到它. 这是因为BIO ...