算法:DP
一开始想DP,怎么想也想不出来,无奈写了一个搜索,虽然说加了位运算了,但是依旧超时。
说下DP的思路。
这道题唯一的做法就是将菱形进行转化,转化成一个尖冲左的三角形,我们用f[i,j]表示前i列安置了j个诸侯,第i列一定放置了诸侯一共存在的方案数,用l[i]表示第i列有多少行。那么:
f[0,0]=1
f[i,j]=Σf[k,j-1]*(l[i]-(j-1))
即前k列放置了j-1个诸侯,那么第i列有j-1个位置不能放诸侯,运用乘法原理再统计一下。
一开始想DP,怎么想也想不出来,无奈写了一个搜索,虽然说加了位运算了,但是依旧超时。
说下DP的思路。
这道题唯一的做法就是将菱形进行转化,转化成一个尖冲左的三角形,我们用f[i,j]表示前i列安置了j个诸侯,第i列一定放置了诸侯一共存在的方案数,用l[i]表示第i列有多少行。那么:
f[0,0]=1
f[i,j]=Σf[k,j-1]*(l[i]-(j-1))
即前k列放置了j-1个诸侯,那么第i列有j-1个位置不能放诸侯,运用乘法原理再统计一下。
蒟蒻的搜索:
program empire;
const
maxn=100;
maxm=19801;
var
n,m,ans:longint;
procedure init;
begin
readln(n,m);
if m>n then
begin
writeln(0);
close(input);
close(output);
halt;
end;
end;
procedure dfs(zt,rest,line:longint);
var
i:longint;
begin
if (line=n shl 1) and (rest<>0) then exit;
if rest=0 then
begin
inc(ans);
ans:=ans mod 504;
exit;
end;
if line<=n then
begin
for i:=n-line to n+line-2 do
begin
if ((1 shl i) and (zt))=0 then
begin
zt:=zt+1 shl i;
dec(rest);
dfs(zt,rest,line+1);
zt:=zt-1 shl i;
inc(rest);
end;
end;
end
else
begin
for i:=line-n to 3*n-line-2 do
begin
if ((1 shl i) and (zt))=0 then
begin
zt:=zt+1 shl i;
dec(rest);
dfs(zt,rest,line+1);
zt:=zt-1 shl i;
inc(rest);
end;
end;
end;
dfs(zt,rest,line+1);
end;
begin
assign(input,'empire.in'); reset(input);
assign(output,'empire.out'); rewrite(output);
init;
dfs(0,m,1);
writeln(ans);
close(input); close(output);
end.
5万+

被折叠的 条评论
为什么被折叠?



