首页 > 代码库 > SCOI2005互不侵犯King

SCOI2005互不侵犯King

1087: [SCOI2005]互不侵犯King

Time Limit: 10 Sec  Memory Limit: 162 MB
Submit: 1499  Solved: 872
[Submit][Status]

Description

在N×N的棋盘里面放K个国王,使他们互不攻击,共有多少种摆放方案。国王能攻击到它上下左右,以及左上左下右上右下八个方向上附近的各一个格子,共8个格子。

Input

只有一行,包含两个数N,K ( 1 <=N <=9, 0 <= K <= N * N)

Output

方案数。

Sample Input

3 2

Sample Output

16

HINT

 

Source

题解:

终于A了这道题。。。

其实意识到对安放的国王总个数有限制,那就应该是DP了

又因为是在棋盘上,所以以每行为状态进行转移

又因为n很小,所以状压DP。。。

主要是做一些预处理

代码:

 1 var  tot,n,i,j1,j2,j,k,l:longint; 2      s:ansistring; 3      ans:int64; 4      a:array[0..1000,0..1000] of boolean; 5      f:array[0..10,0..1000,0..100] of longint; 6      can:array[0..1000] of boolean; 7      calc:array[0..1000] of longint; 8 function check(x,y:longint):boolean; 9  var s1,s2:ansistring;10      i:longint;11   begin12     s1:=binstr(x,n);13     s2:=binstr(y,n);14     for i:=1 to n do15      if (s1[i]=1) and ((s2[i-1]=1) or (s2[i]=1) or (s2[i+1]=1)) then exit(false);16     exit(true);17   end;18 function cann(x:longint):boolean;19  var s:ansistring;20      i:longint;21   begin22     s:=binstr(x,n);23     for i:=2 to n do if (s[i]=1) and (s[i]=s[i-1]) then exit(false);24     exit(true);25   end;26 27 procedure init;28  begin29    readln(n,k);30    tot:=1<<n-1;31    for i:=0 to tot do32     begin33       calc[i]:=0;34       s:=binstr(i,n);35       for j:=1 to n do if s[j]=1 then inc(calc[i]);36     end;37    fillchar(f,sizeof(f),0);38    for i:=0 to tot do f[1,i,calc[i]]:=1;39    for i:=0 to tot do40     if cann(i) then can[i]:=true;41   for i:=0 to tot do42    if can[i] then43     for j:=0 to tot do44      if can[j] then45       if check(i,j) then a[i,j]:=true;46   //for i:=1 to tot do writeln(can[i], ,calc[i]);47  end;48 procedure main;49  begin50    for i:=2 to n do51      for j1:=0 to tot do52       if can[j1] then53        for l:=calc[j1] to k do54         for j2:=0 to tot do55          if (can[j2]) and (a[j1,j2]) then56           inc(f[i,j1,l],f[i-1,j2,l-calc[j1]]);57   // for i:=1 to n do58   //  for j:=0 to tot do59   //   for l:=1 to n do writeln(f[i,j,l]);60    ans:=0;61    for i:=0 to tot do if can[i] then inc(ans,f[n,i,k]);62    writeln(ans);63   end;64 begin65   assign(input,input.txt);assign(output,output.txt);66   reset(input);rewrite(output);67   init;68   main;69   close(input);close(output);70 end.                          
View Code