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的棋盘 ...
随机推荐
- Passpoint R1
Passpoint R1 自从 Android 6.0 支持从网络下载包含配置文件和凭据信息的特殊文件来配置 Passpoint R1(第 1 版)凭据,Android 就一直支持 Passpoint ...
- NodeJS学习笔记 (22)全局对象-global
https://github.com/chyingp/nodejs-learning-guide
- Decorator - 利用装饰器武装前端代码
历史 以前做后端时,接触过一点Spring,也是第一次了解DI.IOC等概念,面向切面编程,对于面向对象编程还不怎么熟练的情况下,整个人慌的一批,它的日志记录.数据库配置等都非常方便,不回侵入到业务代 ...
- iOS下调用元素的focus方法,input元素不聚焦,键盘不弹起的问题
页面元素 <input type="text" ref="elInput"/> <div style="margin-top:20p ...
- JAVA版本区块链钱包核心代码
Block.java package com.ppblock.blockchain.core; import java.io.Serializable; /** * 区块 * @author yang ...
- 巧用MAC地址表
对于身处网络环境的人来说,不少朋友应该遇到过这种的情况:某一个终端找不到接在了哪一个交换机口上,也不知道数据包怎样走的. ok,那么这时候MAC地址表就作用了,拿下图的实验环境(H3C)来说好了 环境 ...
- MyBatis学习总结(17)——Mybatis分页插件PageHelper
如果你也在用Mybatis,建议尝试该分页插件,这一定是最方便使用的分页插件. 分页插件支持任何复杂的单表.多表分页,部分特殊情况请看重要提示. 想要使用分页插件?请看如何使用分页插件. 物理分页 该 ...
- 二叉树、B树、B+树、B*树、LSM树
HBase 对于数据产品,底层存储架构直接决定了数据库的特性和使用场景.RDBMS(关系型数据库)使用 B树 及 B+树 作为数据存储结构. HBase 使用 LSM树. . 二叉树 ...
- 《R实战》读书笔记二
第一章 R简单介绍 本章概要 1安装R 2理解R语言 3执行R程序 本章所介绍的内容概括例如以下. 一个典型的数据分析步骤如图1所看到的. 图1:典型数据分析步骤 简而言之,现今的数据分析要求我们从多 ...
- doT.js灵活运用之嵌入使用
基础的base_info_area <div id="base_info_area"></div> <script type="text/h ...