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进制来表示每一行的状态表示(每一位表示这一格属于第几个联通块)
因为所有的黑色块都必须联通,所以上面的每一个不同的联通块至少有一个要延伸到下面来,这个转移的时候注意一下
对于每一个状态,枚举要下一层涂黑哪些块,然后转移,最后一层黑色都属于同一联通块才能更新答案
(这个代码其实是错的...下面还有一个)
1 const 2 maxn=102; 3 type 4 node=record 5 x,y:longint; 6 end; 7 aa=array[0..5]of longint; 8 var 9 f:array[0..maxn,0..1204]of longint; 10 a:array[0..maxn]of longint; 11 n:longint; 12 13 procedure init; 14 var 15 i,j:longint; 16 s:char; 17 begin 18 readln(n); 19 for i:=1 to n do 20 begin 21 for j:=1 to 5 do 22 begin 23 read(s); 24 a[i]:=a[i]<<1+ord(s)-ord('0'); 25 end; 26 readln; 27 end; 28 while n>0 do 29 begin 30 if a[n]>0 then break; 31 dec(n); 32 end; 33 if n=0 then 34 begin 35 write(0); 36 halt; 37 end; 38 end; 39 40 procedure get(var a:aa); 41 var 42 i,j,k,c:longint; 43 begin 44 c:=1; 45 for i:=1 to 3 do 46 for j:=1 to 5 do 47 if a[j]=i then 48 begin 49 if i=c then inc(c); 50 k:=j; 51 while (k>1) and (a[k-1]>0) do 52 begin 53 dec(k); 54 a[k]:=i; 55 end; 56 k:=j; 57 while (k<5) and (a[k+1]>0) do 58 begin 59 inc(k); 60 a[k]:=i; 61 end; 62 end; 63 dec(c); 64 for i:=1 to 5 do 65 if a[i]=4 then 66 begin 67 if a[i-1]>0 then a[i]:=c 68 else 69 begin 70 inc(c); 71 a[i]:=c; 72 end; 73 end; 74 end; 75 76 function bit(x:longint):longint; 77 begin 78 if x=0 then exit(0); 79 exit(bit(x-(x and -x))+1); 80 end; 81 82 var 83 q:array[0..maxn*1024]of node; 84 85 procedure work; 86 var 87 head,tail,i,j,k,ans,save:longint; 88 s,t:aa; 89 flag:boolean; 90 begin 91 fillchar(f,sizeof(f),1); 92 t[0]:=0; 93 ans:=500; 94 f[0,0]:=0; 95 q[1].x:=0; 96 q[1].y:=0; 97 head:=1; 98 tail:=1; 99 while head<=tail do 100 begin 101 save:=q[head].y; 102 for i:=1 to 5 do 103 begin 104 s[i]:=q[head].y and 3; 105 q[head].y:=q[head].y>>2; 106 end; 107 q[head].y:=save; 108 if q[head].x=n then 109 begin 110 flag:=true; 111 for i:=1 to 5 do 112 if s[i]>1 then flag:=false; 113 if flag then 114 if ans>f[q[head].x,q[head].y] then ans:=f[q[head].x,q[head].y]; 115 inc(head); 116 continue; 117 end; 118 for i:=0 to 31 do 119 if i and a[q[head].x+1]=0 then 120 begin 121 for j:=1 to 5 do 122 t[j]:=(((a[q[head].x+1]+i)>>(j-1))and 1)*4; 123 k:=0; 124 for j:=1 to 5 do 125 if (s[j]>0) and (t[j]>0) then 126 begin 127 t[j]:=s[j]; 128 k:=k or (1<<s[j]); 129 end; 130 flag:=true; 131 for j:=1 to 5 do 132 if (s[j]>0) and (k and (1<<s[j])=0) then flag:=false; 133 if flag=false then continue; 134 get(t); 135 k:=0; 136 for j:=5 downto 1 do 137 k:=k<<2+t[j]; 138 if f[q[head].x+1,k]>500 then 139 begin 140 inc(tail); 141 q[tail].x:=q[head].x+1; 142 q[tail].y:=k; 143 end; 144 if f[q[head].x+1,k]>f[q[head].x,q[head].y]+bit(i) then f[q[head].x+1,k]:=f[q[head].x,q[head].y]+bit(i); 145 end; 146 inc(head); 147 end; 148 write(ans); 149 end; 150 151 begin 152 init; 153 work; 154 end.
为什么会错呢,我写这个的时候,头脑有点乱,导致少考虑了一种情况(因为转移的时候联通块我是乱搞的)
2
11101
10111
这个我就会错
上面我是用10222表示的,然后转移到下面
就变成了14202然后把1附近的改成1(下一行的我全部用4来表示),就变成了11102,结果就错了
下面是改正后的代码
感谢zky和TimeMachine的帮助,查出了这个不易发现的错误,对于前面那个代码AC了我只能说数据太弱,刚好没出到这种数据
1 const 2 maxn=102; 3 type 4 node=record 5 x,y:longint; 6 end; 7 aa=array[0..6]of longint; 8 var 9 f:array[0..maxn,0..1204]of longint; 10 a:array[0..maxn]of longint; 11 fa:array[1..4]of longint; 12 flag:array[1..4]of boolean; 13 n:longint; 14 15 procedure init; 16 var 17 i,j:longint; 18 s:char; 19 begin 20 readln(n); 21 for i:=1 to n do 22 begin 23 for j:=1 to 5 do 24 begin 25 read(s); 26 a[i]:=a[i]<<1+ord(s)-ord('0'); 27 end; 28 readln; 29 end; 30 while n>0 do 31 begin 32 if a[n]>0 then break; 33 dec(n); 34 end; 35 if n=0 then 36 begin 37 write(0); 38 halt; 39 end; 40 end; 41 42 procedure change(var a:aa;b,c:longint); 43 var 44 i:longint; 45 begin 46 for i:=1 to 5 do 47 if a[i]=b then 48 begin 49 a[i]:=c; 50 if (a[i-1]<>0) and (a[i-1]<10) then change(a,a[i-1],c); 51 if (a[i+1]<>0) and (a[i+1]<10) then change(a,a[i+1],c); 52 end; 53 end; 54 55 procedure get(var a:aa); 56 var 57 i,c:longint; 58 begin 59 c:=10; 60 for i:=1 to 5 do 61 if (a[i]<>0) and (a[i]<10) then 62 begin 63 inc(c); 64 change(a,a[i],c); 65 end; 66 for i:=1 to 5 do 67 if a[i]>0 then dec(a[i],10); 68 end; 69 70 function bit(x:longint):longint; 71 begin 72 if x=0 then exit(0); 73 exit(bit(x-(x and -x))+1); 74 end; 75 76 var 77 q:array[0..maxn*1024]of node; 78 79 procedure work; 80 var 81 head,tail,i,j,k,ans,save:longint; 82 s,t:aa; 83 flag:boolean; 84 begin 85 fillchar(f,sizeof(f),1); 86 t[0]:=0; 87 t[6]:=0; 88 ans:=500; 89 f[0,0]:=0; 90 q[1].x:=0; 91 q[1].y:=0; 92 head:=1; 93 tail:=1; 94 while head<=tail do 95 begin 96 save:=q[head].y; 97 for i:=1 to 5 do 98 begin 99 s[i]:=q[head].y and 3; 100 q[head].y:=q[head].y>>2; 101 end; 102 q[head].y:=save; 103 if q[head].x=n then 104 begin 105 flag:=true; 106 for i:=1 to 5 do 107 if s[i]>1 then flag:=false; 108 if flag then 109 if ans>f[q[head].x,q[head].y] then ans:=f[q[head].x,q[head].y]; 110 inc(head); 111 continue; 112 end; 113 for i:=0 to 31 do 114 if i and a[q[head].x+1]=0 then 115 begin 116 for j:=1 to 5 do 117 t[j]:=(((a[q[head].x+1]+i)>>(j-1))and 1)*(j+3); 118 k:=0; 119 for j:=1 to 5 do 120 if (s[j]>0) and (t[j]>0) then 121 begin 122 t[j]:=s[j]; 123 k:=k or (1<<s[j]); 124 end; 125 flag:=true; 126 for j:=1 to 5 do 127 if (s[j]>0) and (k and (1<<s[j])=0) then flag:=false; 128 if flag=false then continue; 129 get(t); 130 k:=0; 131 for j:=5 downto 1 do 132 k:=k<<2+t[j]; 133 if f[q[head].x+1,k]>500 then 134 begin 135 inc(tail); 136 q[tail].x:=q[head].x+1; 137 q[tail].y:=k; 138 end; 139 if f[q[head].x+1,k]>f[q[head].x,q[head].y]+bit(i) then f[q[head].x+1,k]:=f[q[head].x,q[head].y]+bit(i); 140 end; 141 inc(head); 142 end; 143 write(ans); 144 end; 145 146 begin 147 init; 148 work; 149 end.