求一个 n*m 的矩形用 1*2 的矩形进行覆盖的方法总数
状态压缩的动态规划
首先进行枚举,枚举出 flag[p][q] 表示 p 状态可以到达 q 状态,那么就可以进行动态规划了, opt[i][s] 可以更新 opt[i+1][k], 其中 flag[s][k]=true ,最后所求
为 opt[n][max]( 注意初始值
为 opt[0][max]=1)
{
pku2411 Mondriaan's Dream
By largelymfs
Accepted 25840K 1922MS
Date:2010-05-30 15:05
状态压缩动态规划
}
Program Ex;
Const
Infile = 'pku2411.in';
Outfile = 'pku2411.out';
maxn=12;
Var
flag : Array[0..5000, 0..5000] Of Boolean;
opt : Array[0..maxn, 0..5000] Of int64;
maxsize, n, m : longint;
Procedure Dfs(pp, qq, k : longint);
var
tmp : longint;
begin
If k>m then begin
flag[pp][qq] := true;
Exit;
end;
if pp And (1 shl (m-k))=0 Then begin
tmp := qq + 1 shl (m-k);
//If (k<=m-1) And (pp And (1 shl (m-k-1))<>0) Then dfs(pp, tmp+1 shl (m-k-1), k+2);
dfs(pp, tmp, k+1);
end
Else Begin
if (k<=m-1) And (pp And (1 shl (m-k-1))<>0) then dfs(pp, qq+1 shl (m-k)+1 shl (m-k-1), k+2);
dfs(pp, qq, k+1);
end;
end;
Procedure Prepare;
Var
i : longint;
begin
maxsize := (1 shl m)-1;
Fillchar(flag, sizeof(flag), 0);
For i := 0 To maxsize Do Dfs(i, 0, 1);
End;
Procedure Main;
var
i, j, k : longint;
begin
Fillchar(opt, sizeof(opt), 0);
opt[0][maxsize] := 1;
For i := 0 to n-1 Do
For j := 0 to maxsize Do Begin
If opt[i][j]=0 then Continue;
For k := 0 To maxsize Do
If flag[j][k] then begin
opt[i+1][k] := opt[i+1][k]+opt[i][j];
end;
end;
writeln(opt[n][maxsize]);
End;
Begin
Assign(Input, INfile);Reset(input);Assign(Output, OUtfile);Rewrite(Output);
Readln(n, m);
While (n<>0) Or (m<>0) Do begin
Prepare;Main;
Readln(n, m);
end;
Close(Input);Close(Output);
End.
优化
当n<m时交换m,n
如果m,n均为奇数时无解
{
pku2411 Mondriaan's Dream
By largelymfs
Accepted 25876K 1313MS
Date:2010-05-30 15:05
状态压缩动态规划
}
Program Ex;
Const
Infile = 'pku2411.in';
Outfile = 'pku2411.out';
maxn=12;
Var
flag : Array[0..5000, 0..5000] Of Boolean;
opt : Array[0..maxn, 0..5000] Of int64;
maxsize, n, m, tt : longint;
Procedure Dfs(pp, qq, k : longint);
var
tmp : longint;
begin
If k>m then begin
flag[pp][qq] := true;
Exit;
end;
if pp And (1 shl (m-k))=0 Then begin
tmp := qq + 1 shl (m-k);
dfs(pp, tmp, k+1);
end
Else Begin
if (k<=m-1) And (pp And (1 shl (m-k-1))<>0) then dfs(pp, qq+1 shl (m-k)+1 shl (m-k-1), k+2);
dfs(pp, qq, k+1);
end;
end;
Procedure Prepare;
Var
i : longint;
begin
maxsize := (1 shl m)-1;
Fillchar(flag, sizeof(flag), 0);
For i := 0 To maxsize Do Dfs(i, 0, 1);
End;
Procedure Main;
var
i, j, k : longint;
begin
Fillchar(opt, sizeof(opt), 0);
opt[0][maxsize] := 1;
For i := 0 to n-1 Do
For j := 0 to maxsize Do Begin
If opt[i][j]=0 then Continue;
For k := 0 To maxsize Do
If flag[j][k] then begin
opt[i+1][k] := opt[i+1][k]+opt[i][j];
end;
end;
writeln(opt[n][maxsize]);
End;
Begin
Assign(Input, INfile);Reset(input);Assign(Output, OUtfile);Rewrite(Output);
Readln(n, m);
While (n<>0) Or (m<>0) Do begin
If (n mod 2=1) And (m mod 2=1) then begin
writeln(0);
end
Else Begin
If m>n Then Begin tt := m;m := n;n := tt;End;
Prepare;Main;
end;
Readln(n, m);
end;
Close(Input);Close(Output);
End.