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的棋盘 ...
随机推荐
- twig 模板引擎使渲染视图更加优雅
在使用 laravel 的时候接触过 blade 模板引擎.在学习的时候,接触到了另外一个强大的模板引擎:twig 官网:https://twig.sensiolabs.org/ 中文手册:http: ...
- webStrom的破解以及汉化
破解方法: 把JetbrainsCrack-3.1-release-enc.jar包放到bin目录下,然后把webstorm64.exe.vmoptions文件用文本打开, 在最后面加上一句-java ...
- 题解 CF896C 【Willem, Chtholly and Seniorious】
貌似珂朵莉树是目前为止(我学过的)唯一一个可以维护区间x次方和查询的高效数据结构. 但是这玩意有个很大的毛病,就是它的高效建立在数据随机的前提下. 在数据随机的时候assign操作比较多,所以它的复杂 ...
- 【Uva 11584】Partitioning by Palindromes
[Link]:https://cn.vjudge.net/contest/170078#problem/G [Description] 给你若干个只由小写字母组成的字符串; 问你,这个字符串,最少能由 ...
- ECNUOJ 2855 贪吃蛇
贪吃蛇 Time Limit:1000MS Memory Limit:65536KBTotal Submit:480 Accepted:109 Description 相信很多人都玩过这个游戏,当然 ...
- 怎么打开/查看MySQL的SQL记录
mysql在执行sql的时候会在日志当中记录很多信息,当然包括执行的所有语句.下面以使用navicat for mysql为例,来展示一下如何打开/查看MySQL的SQL记录: 打开navicat f ...
- Spring 容器(一)
Source null instanceof Object 语法是正确的 Source定义得到输入流的方法 Resource继承Source,定义判断流是否存在.是否打开等方法 BaseResourc ...
- Win8.1应用开发之文件操作
在操作文件之前,先相应用的应用功能声明进行设定.用户通过C#(非UI)对win8.1上的文件进行訪问,仅仅能局限于图片,音乐,视频和文档四个目录. 而通过文件选取器则能訪问到整个系统的文件. (一)应 ...
- SQL传数组到存储过程中
方法一 CREATE PROC D_t_Base_Employee @str varchar(100) as declare @sql varchar(1000) set @sql='DELETE E ...
- 自动与因特网时间服务器同步 NTP 服务器 pool.ntp.org, 120.24.166.46 端口 123
自动与因特网时间服务器同步 NTP 服务器 pool.ntp.org 海康提供的NTP服务器 120.24.166.46 端口 123