• Day algorithm [more information] • Fourteenth Olympiad 1592 through a: [Example 1] Kings solution to a problem

  Ado, directly on the question:


1592: King [Example 1]


Time limit: 500 ms memory limit: 65536 KB
submitted Number: Number 290 by: 111 

Description [title]

From the original title: SGU 223

In  place of the n × n chessboard  k-King, who can attack adjacent  Total 8 lattice, find that they can not attack each program.

[Enter]

Only one line, comprising two integers  n and  k.

[Output]

The total number of each data of a behavioral program, if the output can be placed  0.

[Sample input]

3 2

[Sample Output]

16

【prompt】

Sample input 2

 

4 4

 

Sample output 2

 

79

 

Data range and tips:

For all data, 1≤n≤10,0≤k≤n 2  .

【source】


no

  Have to say, this question is still too much like the n queens. See this question link: poke here oh ~

  But the Queen would be a king, not a pit on the map only.

  However, we can first look at the size of the data, all of a sudden I was scared to. n Only 10, k is only 100, but although the data is small, but really a search to a search them, it may really be exponential complexity, certainly not. 

  So we have to choose optimization, This question belongs to the state compression dynamic programming class, in small series have been used long ago, in fact, it means the use of binary optimization.

  As we all know, it is this binary: 1,010,110, a bunch of 0 and 1, but if your map is composed of 1s and 0s, then it can do optimization.

  Illustration of this:

  Actually copy down from an increase through the articles.

  Then the row data is condensed into a number, and then we can just find the highest level of 1 x & -x with lowbit principle in dealing with the 1 (do not ask me why, other heavyweights are not very clear).

  好了,回归正题,这道题是动态规划题,那么怎样设计状态呢?

  我们要在n*n的棋盘上放k个国王,那么我们不妨用f[i][j][k]来表示第i行的状态是a[j](二进制表示),目前为止放了k个棋子。

  显然f[i][j][k]=sum{i-1,l,k-num[j]}(不发生冲突),其中l是,枚举上一行状态的变量,num[j]是a[j]这一状态可以放置的国王数。

  行了,其他的都看注释吧,要不然不好解释,代码如下:

 1 #include<iostream>
 2 using namespace std;
 3 long long n,K,num[1000],a[1000],sum,ans,f[300][300][300];
 4 void pre()
 5 {
 6     int cnt=0;//记录方案数 
 7     for(int i=0;i<(1<<n);i++)//注意,这里模拟的是一行的所有状态,而不是行数 
 8     {
 9         if(i&(i<<1)) continue;//如果结果不是0,那么就会有1是挨着的,不合法 
10         cnt=0;
11         for(int j=0;j<n;j++) if((1<<j)&i) cnt++;//如果i的二进制表示下的j位有1,那么就记录 
12         a[++sum]=i;//记录状态 
13         num[sum]=cnt;//记录可以放国王的数量 
14     }
15 }
16 void dp()
17 {
18     f[0][1][0]=1;//显然第0行第一位上可以放一个国王 
19     for(int i=1;i<=n;i++)
20     for(int j=1;j<=sum;j++)
21     for(int k=0;k<=K;k++)
22     {
23         if(k>=num[j])//先看能不能减 
24         for(int l=1;l<=sum;l++)
25         if(!(a[l]&a[j]) && !(a[l]&(a[j]<<1)) && !(a[l]&(a[j]>>1)))//看看国王和上一行的国王起不起冲突 
26         f[i][j][k]+=f[i-1][l][k-num[j]];
27     }
28     for(int i=1;i<=sum;i++) ans+=f[n][i][K];//最后一行的所有状态都要加上 
29     cout<<ans;
30 }
31 int main()
32 {
33     cin>>n>>K;
34     pre();dp();
35     return 0;
36 }

Guess you like

Origin www.cnblogs.com/TFLS-gzr/p/11202543.html