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的棋盘 ...
随机推荐
- hp服务器安装exsi5.5
启动按f8进入raid制造页面: 1. 插入exsi5.5光盘 2. 按下开机键(开机比较慢需要等待一段时间) 3. 进入启动项目界面(插入光盘后启动会让你选择启动项.选择1光盘启动) 接下来按 ...
- Chromium Graphics: Video Playback and Compositor
Video Playback and Compositor Authors: jamesr@chromium.org, danakj@chromium.org The Chromium composi ...
- uname---用于打印当前系统相关信息
uname命令用于打印当前系统相关信息(内核版本号.硬件架构.主机名称和操作系统类型等). 语法 uname(选项) 选项 -a或--all:显示全部的信息: -m或--machine:显示电脑类型: ...
- 小白学开发(iOS)OC_ 经常使用结构体(2015-08-14)
// // main.m // 经常使用结构体 // // Created by admin on 15/8/13. // Copyright (c) 2015年 admin. All rig ...
- js易错点总结及 常见面试的坑
最近在研究Javascript发现了其中一些比较灵异的事情.有点让人感到无语比如: var arr = [], arr2 = {}; console.log(typeof(arr) === typeo ...
- Magento--判断checkout中是否使用了coupon code
在checkout页面中,如果想判断顾客是否有使用coupon code,可以通过checkout session来进行判断.以下代码会返回checkout中使用的coupon code或者返回空(当 ...
- JAVA使用Gson解析json数据,实例
封装类Attribute: public class Attribute { private int id; private String name; private int age; public ...
- 简述SQL with(unlock)与with(readpast)
所有Select加 With (NoLock)解决阻塞死锁,在查询语句中使用 NOLOCK 和 READPAST 处理一个数据库死锁的异常时候,其中一个建议就是使用 NOLOCK 或者 READPAS ...
- try{futureGirl}catch(Exception){"Kill All Trouble"}——echarts样式
首先先给未来女,解释一下题目吧.这是段代码,我再try{}括号里写了你,意思我会保护你.后面的catch(Exception)是捕捉你的所有麻烦,交给我解决. 今天收工较早,拖着疲惫是身躯回到宿舍,简 ...
- webpack+react实现echarts可视化配置
先上效果 开发环境要求 需要事先安装node及npm 前期准备 1.创建文件夹react-echarts-editor2.在项目根目录(以下称根目录)下创建src目录3.在项目根目录下创建dist目录 ...