bzoj2331 : [SCOI2011]地板 2011-12-20
2331: [SCOI2011]地板Time Limit: 5 Sec Memory Limit: 128 MB
Submit: 128 Solved: 54
[Submit][Status][Discuss]Description
lxhgww的小名叫“小L”,这是因为他总是很喜欢L型的东西。小L家的客厅是一个的矩形,现在他想用L型的地板来铺满整个客厅,客厅里有些位置有柱子,不能铺地板。现在小L想知道,用L型的地板铺满整个客厅有多少种不同的方案?
需要注意的是,如下图所示,L型地板的两端长度可以任意变化,但不能长度为0。铺设完成后,客厅里面所有没有柱子的地方都必须铺上地板,但同一个地方不能被铺多次。
Input
输入的第一行包含两个整数,R和C,表示客厅的大小。
接着是R行,每行C个字符。’_’表示对应的位置是空的,必须铺地板;’*’表示对应的位置有柱子,不能铺地板。
Output
输出一行,包含一个整数,表示铺满整个客厅的方案数。由于这个数可能很大,只需输出它除以20110520的余数。
Sample Input2 2
*_
__
Sample Output1
HINT
R*C<=100
Source
——————————————————————
和Ural 1519 Formula 1差不多。就是状态转移不一样,详见程序。
——————————————————————
1 Program Stone; 2 3 var i,j,k,l,n,m:longint; 4 5 map:array[1..50,1..50]of char; 6 7 f:array[0..1,1..200000]of record opt,v:longint;end; 8 9 o:array[0..1,0..200000]of longint; 10 11 q:array[0..12]of longint; 12 13 t1,t2,lap,num1,num2,opt,tmp:longint; 14 15 procedure init; 16 17 var i,j:longint; 18 19 begin 20 21 readln(n,m); //因为n*m<=100,所以必要时需要将旋转一下图。 22 23 if m<n then for i:=1 to n do 24 25 begin 26 27 for j:=1 to m do 28 29 read(map[i,j]); 30 31 readln; 32 33 end 34 35 else begin 36 37 for i:=1 to n do 38 39 begin 40 41 for j:=1 to m do 42 43 read(map[j,i]); 44 45 readln; 46 47 end; 48 49 i:=n;n:=m;m:=i; 50 51 end; 52 53 end; 54 55 56 57 Function refer(opt,x:longint):longint; 58 59 begin 60 61 refer:=opt div q[x-1] mod 3; 62 63 end; 64 65 66 67 Procedure update(opt,v:longint); 68 69 begin 70 71 if (j=m)and(refer(opt,m+1)<>0) then exit; 72 73 if o[1-lap,opt]=0 then begin 74 75 inc(num2); 76 77 o[1-lap,opt]:=num2; 78 79 f[1-lap,num2].opt:=opt; 80 81 f[1-lap,num2].v:=v; 82 83 end 84 85 else f[1-lap,o[1-lap,opt]].v:=(v+f[1-lap,o[1-lap,opt]].v)mod 20110520; 86 87 end; 88 89 90 91 Function change(opt,x,s:longint):longint; 92 93 begin 94 95 change:=opt+(s-opt div q[x-1] mod 3)*q[x-1]; 96 97 end; 98 99 Begin 100 101 assign(input,'input.in');reset(input); 102 103 init; 104 105 q[0]:=1; 106 107 for i:=1 to m+1 do q[i]:=q[i-1]*3; 108 109 lap:=0;num1:=1; 110 111 f[lap,1].v:=1;f[lap,1].opt:=0; 112 113 o[lap,0]:=1; 114 115 for i:=1 to n do 116 117 for j:=1 to m do 118 119 begin 120 121 for k:=1 to num1 do 122 123 begin 124 125 opt:=f[lap,k].opt; 126 127 if j=1 then opt:=opt*3; 128 129 t1:=refer(opt,j); 130 131 t2:=refer(opt,j+1); 132 133 if (t1=0)and(t2=0) then //状态转移 134 135 begin 136 137 if map[i,j]='*' then begin update(opt,f[lap,k].v);continue;end; 138 139 tmp:=change(change(opt,j,1),j+1,1); 140 141 update(tmp,f[lap,k].v); 142 143 tmp:=change(change(opt,j,0),j+1,2); 144 145 update(tmp,f[lap,k].v); 146 147 tmp:=change(change(opt,j,2),j+1,0); 148 149 update(tmp,f[lap,k].v); 150 151 continue; 152 153 end; 154 155 if (map[i,j]='*')or(t1+t2=3)or((t1=1)and(t2=1)) then continue;//淘汰状态 156 157 if (t1=2)and(t2=2) then 158 159 begin 160 161 tmp:=change(change(opt,j,0),j+1,0); 162 163 update(tmp,f[lap,k].v); 164 165 continue; 166 167 end; 168 169 if (t1=0)or(t2=0) then 170 171 begin 172 173 tmp:=change(change(opt,j,t2),j+1,t1); 174 175 update(tmp,f[lap,k].v); 176 177 if t1+t2<>2 then 178 179 begin 180 181 tmp:=change(change(opt,j,0),j+1,0); 182 183 update(tmp,f[lap,k].v); 184 185 end 186 187 else 188 189 begin 190 191 tmp:=change(change(opt,j,t1 div 2),j+1,t2 div 2); 192 193 update(tmp,f[lap,k].v); 194 195 end; 196 197 end; 198 199 end; 200 201 for k:=1 to num1 do o[lap,f[lap,k].opt]:=0; 202 203 lap:=1-lap;num1:=num2;num2:=0; 204 205 end; 206 207 writeln(f[lap,o[lap,0]].v); 208 209 close(input); 210 211 end.
_____MildTheorem