诸侯安置(empire)

算法: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个位置不能放诸侯,运用乘法原理再统计一下。

蒟蒻的搜索:

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.
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
红包 添加红包
表情包 插入表情
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值