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 ...
随机推荐
- PHP面向对象:类型提示
PHP是弱类型语言,向方法传递参数时候也不太区分类型.这样的使用会引起很多的问题,PHP开发者认为,这些问题应该是由代码书写者在书写代码时进行检验以避免. 没有类型提示很危险 下面的代码可能会出现问题 ...
- iframe仿Ajax上传文件
利用iframe框架完成文件上传 前端页面 <!doctype html> <html lang="en"> <head> <meta c ...
- Jersey(1.19.1) - XML Support
As you probably already know, Jersey uses MessageBodyWriters and MessageBodyReaders to parse incomin ...
- Linux 命令 - fg & bg: 将进程切换到前台(后台)运行
后台运行的进程不会受到任何键盘的影响,包括试图用来中断它的 Ctrl-C 键.想要使得进程返回到前台来运行,可以使用 fg 命令来实现. 可以通过在 fg 命令后面加上百分比符号和作业编号(称为 jo ...
- ASP判断当前页面上是否有参数ID传递过来
遇到了一个这样的ASP问题: 在当前页面上判断,是否有参数ID传递过来? 如果没有,显示“没有参数传递过来”. 如果有传递,但值为空,显示“存在参数,但参数为空” <% if (request( ...
- HDOJ2010水仙花数
水仙花数 Time Limit: 2000/1000 MS (Java/Others) Memory Limit: 65536/32768 K (Java/Others)Total Submis ...
- sql常识- UNIQUE
SQL UNIQUE 约束 UNIQUE 约束唯一标识数据库表中的每条记录. UNIQUE 和 PRIMARY KEY 约束均为列或列集合提供了唯一性的保证. PRIMARY KEY 拥有自动定义的 ...
- CSS 元素垂直居中的 6种方法
利用CSS进行元素的水平居中,比较简单,行级元素设置其父元素的text-align center,块级元素设置其本身的left 和 right margins为auto即可.本文收集了六种利用css进 ...
- C# WinForm TextBox添加水印效果
1.新建项目添加WatermarkTextBox类: using System; using System.Collections.Generic; using System.Text; using ...
- OpenGL2-绘制三角形
代码下载 /*** 该例子展示如何使用OpenGL绘制三角形* 为什么说绘制三角形呢 ?三维空间里面,我们看到的机会大多数* 漂亮的模型,建筑,任务,机会都是有三角形网络组成.可以说三角形* 是组成三 ...