您的位置:首页 > 其它

[PKU 2411]Mondriaan's Dream(状压DP)

2009-08-04 16:13 246 查看
[题目大意]

有一个m*n的正方形网格,让你用1*2的骨牌覆盖满这个网格,并且不允许重叠,求方案个数。

[题目分析]

再经典不过的一道状压DP覆盖模型的题目了。这个题很容易想出这样一个方程:

f[i,j]表示前i-1行盖满,第i行使用j这种状态的方案个数。

F[I,J]:=Sum{F[I-1,K]} (K状态能导出J状态)

现在最麻烦的地方变成了,如何确定一个状态I可以由哪几个状态推出来,并且这些状态都是什么。

这个就是DFS了。

一共是几中情况,如果没有空位,就过去,如果有空位,那就放。

放有两种情况:

情况1:如果只有一个空,那就只能竖着放一个。

情况2:如果有两个空,那就可以用横着放一个填满上一行,这样的方案不变

。要么就是直接方一个,继续进行。

[代码]

program PKU_2411;
var
f:array[0..11,0..2048] of int64;
ok:array[0..2048,0..2048] of boolean;
i,j,k,m,n:longint;
procedure dfs(step,now:longint);
begin
if step=m+1 then
begin
ok[i,now]:=true;
exit;
end;
if (1<<(step-1)) and i<>0 then dfs(step+1,now)   //If there is none
else
begin
if (step<=m-1) and ((1<<step) and i=0) then
dfs(step+2,now);                      //If there is two space left
dfs(step+1,now+(1<<(step-1)));               //If there is only one
end;
end;
begin
assign(input,'a.in');
assign(output,'a.out');
reset(input); rewrite(output);
while true do
begin
readln(n,m);
if n+m=0 then break;
if odd(n) and odd(m) then
begin
writeln(0);
continue;
end;
fillchar(f,sizeof(f),0);
fillchar(ok,sizeof(ok),0);
for i:=0 to (1<<m-1) do
dfs(1,0);            {get all status can be with i}
f[0,0]:=1;
for i:=1 to n do
for j:=0 to 1<<m-1 do
for k:=0 to 1<<m-1 do
if ok[j,k] then inc(f[i,k],f[i-1,j]);
writeln(f[n,0]);
end;
close(input); close(output);
end.
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: