1050 棋盘染色 2 - Wikioi
题目描述 Description
有一个5*N的棋盘,棋盘中的一些格子已经被染成了黑色,你的任务是对最少的格子染色,使得所有的黑色能连成一块。
输入描述 Input Description
第一行一个整数N(<=100),接下来N行每行一个长度为5的01串,1表示所在格子已经被染成了黑色,0表示所在格子没有被染色。
输出描述 Output Description
第一行一个整数N(<=100),接下来N行每行一个长度为5的01串,1表示所在格子已经被染成了黑色,0表示所在格子没有被染色。
样例输入 Sample Input
5
11100
11000
10000
01111
11111
样例输出 Sample Output
1
数据范围及提示 Data Size & Hint
N(<=100)
写得要吐了,看了Wikioi后面的题解突然有了灵感(看到了时间复杂度和空间复杂度.....)
状压dp,每一行压连通性,因为只有5列,最多有三个互不相交的联通块,所以可以用4进制来表示每一行的状态表示(每一位表示这一格属于第几个联通块)
因为所有的黑色块都必须联通,所以上面的每一个不同的联通块至少有一个要延伸到下面来,这个转移的时候注意一下
对于每一个状态,枚举要下一层涂黑哪些块,然后转移,最后一层黑色都属于同一联通块才能更新答案
(这个代码其实是错的...下面还有一个)
const
maxn=;
type
node=record
x,y:longint;
end;
aa=array[..]of longint;
var
f:array[..maxn,..]of longint;
a:array[..maxn]of longint;
n:longint; procedure init;
var
i,j:longint;
s:char;
begin
readln(n);
for i:= to n do
begin
for j:= to do
begin
read(s);
a[i]:=a[i]<<+ord(s)-ord('');
end;
readln;
end;
while n> do
begin
if a[n]> then break;
dec(n);
end;
if n= then
begin
write();
halt;
end;
end; procedure get(var a:aa);
var
i,j,k,c:longint;
begin
c:=;
for i:= to do
for j:= to do
if a[j]=i then
begin
if i=c then inc(c);
k:=j;
while (k>) and (a[k-]>) do
begin
dec(k);
a[k]:=i;
end;
k:=j;
while (k<) and (a[k+]>) do
begin
inc(k);
a[k]:=i;
end;
end;
dec(c);
for i:= to do
if a[i]= then
begin
if a[i-]> then a[i]:=c
else
begin
inc(c);
a[i]:=c;
end;
end;
end; function bit(x:longint):longint;
begin
if x= then exit();
exit(bit(x-(x and -x))+);
end; var
q:array[..maxn*]of node; procedure work;
var
head,tail,i,j,k,ans,save:longint;
s,t:aa;
flag:boolean;
begin
fillchar(f,sizeof(f),);
t[]:=;
ans:=;
f[,]:=;
q[].x:=;
q[].y:=;
head:=;
tail:=;
while head<=tail do
begin
save:=q[head].y;
for i:= to do
begin
s[i]:=q[head].y and ;
q[head].y:=q[head].y>>;
end;
q[head].y:=save;
if q[head].x=n then
begin
flag:=true;
for i:= to do
if s[i]> then flag:=false;
if flag then
if ans>f[q[head].x,q[head].y] then ans:=f[q[head].x,q[head].y];
inc(head);
continue;
end;
for i:= to do
if i and a[q[head].x+]= then
begin
for j:= to do
t[j]:=(((a[q[head].x+]+i)>>(j-))and )*;
k:=;
for j:= to do
if (s[j]>) and (t[j]>) then
begin
t[j]:=s[j];
k:=k or (<<s[j]);
end;
flag:=true;
for j:= to do
if (s[j]>) and (k and (<<s[j])=) then flag:=false;
if flag=false then continue;
get(t);
k:=;
for j:= downto do
k:=k<<+t[j];
if f[q[head].x+,k]> then
begin
inc(tail);
q[tail].x:=q[head].x+;
q[tail].y:=k;
end;
if f[q[head].x+,k]>f[q[head].x,q[head].y]+bit(i) then f[q[head].x+,k]:=f[q[head].x,q[head].y]+bit(i);
end;
inc(head);
end;
write(ans);
end; begin
init;
work;
end.
为什么会错呢,我写这个的时候,头脑有点乱,导致少考虑了一种情况(因为转移的时候联通块我是乱搞的)
2
11101
10111
这个我就会错
上面我是用10222表示的,然后转移到下面
就变成了14202然后把1附近的改成1(下一行的我全部用4来表示),就变成了11102,结果就错了
下面是改正后的代码
感谢zky和TimeMachine的帮助,查出了这个不易发现的错误,对于前面那个代码AC了我只能说数据太弱,刚好没出到这种数据
const
maxn=;
type
node=record
x,y:longint;
end;
aa=array[..]of longint;
var
f:array[..maxn,..]of longint;
a:array[..maxn]of longint;
fa:array[..]of longint;
flag:array[..]of boolean;
n:longint; procedure init;
var
i,j:longint;
s:char;
begin
readln(n);
for i:= to n do
begin
for j:= to do
begin
read(s);
a[i]:=a[i]<<+ord(s)-ord('');
end;
readln;
end;
while n> do
begin
if a[n]> then break;
dec(n);
end;
if n= then
begin
write();
halt;
end;
end; procedure change(var a:aa;b,c:longint);
var
i:longint;
begin
for i:= to do
if a[i]=b then
begin
a[i]:=c;
if (a[i-]<>) and (a[i-]<) then change(a,a[i-],c);
if (a[i+]<>) and (a[i+]<) then change(a,a[i+],c);
end;
end; procedure get(var a:aa);
var
i,c:longint;
begin
c:=;
for i:= to do
if (a[i]<>) and (a[i]<) then
begin
inc(c);
change(a,a[i],c);
end;
for i:= to do
if a[i]> then dec(a[i],);
end; function bit(x:longint):longint;
begin
if x= then exit();
exit(bit(x-(x and -x))+);
end; var
q:array[..maxn*]of node; procedure work;
var
head,tail,i,j,k,ans,save:longint;
s,t:aa;
flag:boolean;
begin
fillchar(f,sizeof(f),);
t[]:=;
t[]:=;
ans:=;
f[,]:=;
q[].x:=;
q[].y:=;
head:=;
tail:=;
while head<=tail do
begin
save:=q[head].y;
for i:= to do
begin
s[i]:=q[head].y and ;
q[head].y:=q[head].y>>;
end;
q[head].y:=save;
if q[head].x=n then
begin
flag:=true;
for i:= to do
if s[i]> then flag:=false;
if flag then
if ans>f[q[head].x,q[head].y] then ans:=f[q[head].x,q[head].y];
inc(head);
continue;
end;
for i:= to do
if i and a[q[head].x+]= then
begin
for j:= to do
t[j]:=(((a[q[head].x+]+i)>>(j-))and )*(j+);
k:=;
for j:= to do
if (s[j]>) and (t[j]>) then
begin
t[j]:=s[j];
k:=k or (<<s[j]);
end;
flag:=true;
for j:= to do
if (s[j]>) and (k and (<<s[j])=) then flag:=false;
if flag=false then continue;
get(t);
k:=;
for j:= downto do
k:=k<<+t[j];
if f[q[head].x+,k]> then
begin
inc(tail);
q[tail].x:=q[head].x+;
q[tail].y:=k;
end;
if f[q[head].x+,k]>f[q[head].x,q[head].y]+bit(i) then f[q[head].x+,k]:=f[q[head].x,q[head].y]+bit(i);
end;
inc(head);
end;
write(ans);
end; begin
init;
work;
end.
1050 棋盘染色 2 - Wikioi的更多相关文章
- codevs——1049 棋盘染色
1049 棋盘染色 时间限制: 1 s 空间限制: 128000 KB 题目等级 : 黄金 Gold 题解 查看运行结果 题目描述 Description 有一个5×5的棋盘,上面有一 ...
- [codevs1050]棋盘染色 2
[codevs1050]棋盘染色 2 试题描述 有一个5*N的棋盘,棋盘中的一些格子已经被染成了黑色,你的任务是对最少的格子染色,使得所有的黑色能连成一块. 输入 第一行一个整数N(<=100) ...
- 【wikioi】1049 棋盘染色(迭代深搜)
http://www.wikioi.com/problem/1049/ 这题我之前写没想到迭代加深,看了题解,然后学习了这种搜索(之前我写的某题也用过,,但是不懂专业名词 囧.) 迭代加深搜索就是限制 ...
- codevs 1049 棋盘染色
题目描述 Description 有一个5×5的棋盘,上面有一些格子被染成了黑色,其他的格子都是白色,你的任务的对棋盘一些格子进行染色,使得所有的黑色格子能连成一块,并且你染色的格子数目要最少.读入一 ...
- HDU 5402 Travelling Salesman Problem(棋盘染色 构造 多校啊)
题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=5402 Problem Description Teacher Mai is in a maze wit ...
- [CodeVs1050]棋盘染色2(状态压缩DP)
题目大意:有一个5*N(≤100)的棋盘,棋盘中的一些格子已经被染成了黑色,求最少对多少格子染色,所有的黑色能连成一块. 这题卡了我1h,写了2.6k的代码,清明作业一坨还没做啊...之前一直以为这题 ...
- CODEVS——T 1049 棋盘染色
http://codevs.cn/problem/1049/ 时间限制: 1 s 空间限制: 128000 KB 题目等级 : 黄金 Gold 题解 查看运行结果 题目描述 Descr ...
- hdu5601-N*M bulbs(黑白棋盘染色)
一个矩形,一个人从左上角走到右下角,每走过一个位置把0变成1,1变成0. 求有没有可能他离开之后所有的数都是0 假设这个矩形是一个棋盘,黑白相间. 这样会发现从一个颜色走到相同颜色可以对棋盘不产生任何 ...
- [codevs1049]棋盘染色<迭代深搜>
题目链接:http://codevs.cn/problem/1049/ 昨天的测试题里没有打出那可爱的迭代深搜,所以今天就来练一练. 这道题其实我看着有点懵,拿着题我就这状态↓ 然后我偷偷瞄了一眼hz ...
随机推荐
- crontab执行java命令失效
一.我们常常碰到在shell下执行某个命令能够成功,比如执行一个java程序: java -jar /home/opscoder/topo-audit.jar,但是在crontab下执行会失败. co ...
- HTML5自带的原生定位
使用谷歌的,与百度有偏差,一般不推荐使用 一.window.navigator.geolocation 验证浏览器是否支持 if (window.navigator.geolocation) { ...
- Linux 命令 - cp: 拷贝文件和目录
命令格式 cp [OPTION]... [-T] SOURCE DEST cp [OPTION]... SOURCE... DIRECTORY cp [OPTION]... -t DIRECTORY ...
- 使用spring+mybatis+atomikos+tomcat构建分布式事务
本文通过一个demo,介绍如何使用spring+mybatis+atomikos+tomcat构建在一个事务中涉及两个数据源的web应用. demo功能:实现一个能成功提交和回滚的涉及两个数据库数据源 ...
- document.ready和onload的区别
转自:http://holysonll.blog.163.com/blog/static/2141390932013411112823855/ document.ready和onload的区别——Ja ...
- HDOJ2028Lowest Common Multiple Plus
Lowest Common Multiple Plus Time Limit: 2000/1000 MS (Java/Others) Memory Limit: 65536/32768 K (J ...
- android组件间共享数据的常用方法
使用Intent在激活组件的时候携带数据,以进行数据的传递 使用广播进行组件间数据的伟递 使用外部存储(sharedPreference,文件,数据库,网络)进行组件间数据共享 使用Static静态成 ...
- CSS之显示天气
这个可以有,自从有了这个,以后查询天气就方便多了,哈哈. <!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN&q ...
- self指向函数地址 动态调用函数的简单例子
#import <Foundation/Foundation.h> @interface Person : NSObject - (void)test1; - (void)test2:(N ...
- JavaScript学习笔记(10)——JavaScript语法之操作DOM
1.页面输出用document.write()方法,但是不可以在window.onload中用,否则整个html页面将被覆盖. 2.通过javascript获取对象后,改变对象中的html内容:doc ...