BZOJ 1087 互不侵犯King 状态压缩DP

题目链接:

https://www.lydsy.com/JudgeOnline/problem.php?id=1087

题目大意;

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

思路:

状态压缩,预处理出每一行的合法状态,连续的两个1在一起的状态为不合法状态。

预处理出从上一行到下一行的合法情况,直接每一行推过来即可。

 1 #include<bits/stdc++.h>
 2 #define IOS ios::sync_with_stdio(false);//不可再使用scanf printf
 3 #define Max(a, b) ((a) > (b) ? (a) : (b))//禁用于函数,会超时
 4 #define Min(a, b) ((a) < (b) ? (a) : (b))
 5 #define Mem(a) memset(a, 0, sizeof(a))
 6 #define Dis(x, y, x1, y1) ((x - x1) * (x - x1) + (y - y1) * (y - y1))
 7 #define MID(l, r) ((l) + ((r) - (l)) / 2)
 8 #define lson ((o)<<1)
 9 #define rson ((o)<<1|1)
10 #define Accepted 0
11 #pragma comment(linker, "/STACK:102400000,102400000")//栈外挂
12 using namespace std;
13 inline int read()
14 {
15     int x=0,f=1;char ch=getchar();
16     while (ch<'0'||ch>'9'){if (ch=='-') f=-1;ch=getchar();}
17     while (ch>='0'&&ch<='9'){x=x*10+ch-'0';ch=getchar();}
18     return x*f;
19 }
20 typedef long long ll;
21 const int maxn = 2000000 + 10;
22 const int MOD = 1000000007;//const引用更快,宏定义也更快
23 const int INF = 1e9 + 7;
24 const double eps = 1e-10;
25 const double pi = acos(-1);
26 
27 bool Map[520][520];
28 bool no[520];//判断状态i是否不合法
29 ll dp[10][520][100];//dp[i][j][k] 表示第i行状态为j,且当前放置的数目为k
30 int n, k;
31 void init()
32 {
33     for(int x = 0; x < (1<<n); x++)
34         for(int i = 0; i < n - 1; i++)
35             if((x&(1<<i))&&(x&(1<<(i+1)))){no[x] = 1;break;}
36     for(int x = 0; x < (1<<n); x++)if(!no[x])
37     {
38         for(int y = 0; y < (1<<n); y++)if(!no[y])
39         {
40             bool flag = 1;
41             for(int i = 0; i < n; i++)if(x&(1<<i))
42             {
43                 if(y&(1<<i)){flag = 0; break;}
44                 if(i != 0 && (y&(1<<(i-1)))){flag = 0; break;}
45                 if(i != n && (y&(1<<(i+1)))){flag = 0; break;}
46             }
47             Map[x][y] = flag;
48         }
49     }
50 }
51 inline int f(int x)
52 {
53     int ans = 0;
54     for(int i = 0; i < n; i++)if(x&(1<<i))ans++;
55     return ans;
56 }
57 int main()
58 {
59     cin >> n >> k;
60     init();
61     for(int i = 0; i < (1<<n); i++)if(!no[i])dp[1][i][f(i)] = 1;
62     for(int i = 2; i <= n; i++)
63         for(int x = 0; x < (1<<n); x++)if(!no[x])//该行状态
64             for(int y = 0; y < (1<<n);y++)if(!no[y] && Map[y][x])//上一行状态
65             {
66                 int tmp = f(x);
67                 for(int num = 0; num + tmp <= k; num++)
68                     dp[i][x][num + tmp] += dp[i - 1][y][num];
69             }
70     ll ans = 0;
71     for(int i = 0; i < (1<<n); i++)if(!no[i])ans += dp[n][i][k];
72     cout<<ans<<endl;
73     return 0;
74 }

 

posted @ 2018-10-02 16:28  _努力努力再努力x  阅读(223)  评论(0编辑  收藏  举报