C++之路进阶——状态压缩dp(互不侵犯)

2451 互不侵犯

2005年省队选拔赛四川

时间限制: 1 s

空间限制: 128000 KB

题目等级 : 大师 Master

题目描述 Description

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

输入描述 Input Description

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

输出描述 Output Description

方案数。

样例输入 Sample Input

3 2

样例输出 Sample Output

16

数据范围及提示 Data Size & Hint

1 <=N <=9,  0 <= K <= N * N

题解:

用二进制表示状态,进行dp。

代码:

 1 #include<cstdio>
 2 #include<iostream>
 3 #define maxn 600
 4 #include<algorithm>
 5
 6 using namespace std;
 7
 8 int n,m,b1[maxn],b2[maxn][maxn],sum[maxn];
 9 long long f[10][maxn][maxn];
10
11 int main()
12   {
13       scanf("%d%d",&n,&m);
14       int s=(1<<n)-1;
15       for (int i=0;i<=s;i++)
16          if ((i&(i>>1))==0)
17             {
18                 b1[i]=1;
19                 int q=0;
20                 for (int j=i;j;j=j>>1)
21                     if (j&1)
22                        q++;
23                 sum[i]=q;
24             }
25       for (int i=0;i<=s;i++)
26          if (b1[i])
27                  for (int j=0;j<=s;j++)
28                    if (b1[j]&&(i&j)==0&&((i<<1)&j)==0&&((i>>1)&j)==0)
29                             b2[i][j]=1;
30     for (int i=0;i<=s;i++)
31         f[1][sum[i]][i]=1;
32     for (int i=1;i<n;i++)
33         for (int j=0;j<=s;j++)
34             if (b1[j])
35                 for (int k=0;k<=s;k++)
36                    if (b1[k]&&b2[j][k])
37                       {
38                            for (int q=sum[j];q+sum[k]<=m;q++)
39                               f[i+1][sum[k]+q][k]+=f[i][q][j];
40                        }
41     long long ans=0;
42     for (int i=0;i<=s;i++)
43        ans+=f[n][m][i];
44     printf("%lld\n",ans);
45       return 0;
46   }
时间: 2024-08-07 10:24:58

C++之路进阶——状态压缩dp(互不侵犯)的相关文章

POJ 2288 Islands and Bridges 哈密尔顿路 状态压缩DP

找最长的其实是很裸的状态压缩DP,棘手的地方是要统计数量,其实只要再来一个数组存就好. 不过代码比较长,细节要注意的地方毕较多,wa了很多发,还是要仔细啊 用递推和记忆化搜索分别写了一遍 #include <cstdio> #include <cstring> #include <cmath> #include <algorithm> #include <climits> #include <string> #include <

北大ACM2686——Traveling by Stagecoach~~状态压缩DP

最近才看书,看到状态压缩.对于状态压缩DP,其实就是集合上的DP. 这需要我们了解一些位运算: 集合{0,1,2,3,....,n-1}的子集可以用下面的方法编码成整数 像这样,一些集合运算就可以用如下的方法来操作: 1.空集....................0 2.只含有第i个元素的集合{i}................1 << i 3.含有全部n个元素的集合{0,1,2,3,....,n - 1}.............(1 << n) - 1 4.判断第i个元素是

HDU3768 Shopping(状态压缩DP+spfa)旅行商问题

Shopping Time Limit: 10000/5000 MS (Java/Others)    Memory Limit: 32768/32768 K (Java/Others) Total Submission(s): 577    Accepted Submission(s): 197 Problem Description You have just moved into a new apartment and have a long list of items you need

状态压缩DP

I - 方格取数(1) Crawling in process... Crawling failed Time Limit:5000MS     Memory Limit:32768KB     64bit IO Format:%I64d & %I64u Submit Status Description Input Output Sample Input Sample Output Hint Description 给你一个n*n的格子的棋盘,每个格子里面有一个非负数.   从中取出若干个数,

HDU 3001 Travelling(状态压缩DP+三进制)

题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=3001 题目大意:有n个城市,m条路,每条路都有一定的花费,可以从任意城市出发,每个城市不能经过两次以上,要求经过所有城市并且花费最少,求出最小花费. 解题思路:三进制的状态压缩DP,跟二进制还是有一点不一样的,因为三进制没有直接的位运算,还要自己先做处理利用num[i][j]记录数字i各位的三进制表示方便计算,其他的就跟二进制状态压缩没有太大区别了.还有注意: ①开始要将n个起点初始化,dp[bit

POJ2288Islands and Bridges(状态压缩DP,求最大路和走条数)

Islands and Bridges Time Limit: 4000MS   Memory Limit: 65536K Total Submissions: 8845   Accepted: 2296 Description Given a map of islands and bridges that connect these islands, a Hamilton path, as we all know, is a path along the bridges such that i

POJ 2288 Islands And Bridges 状态压缩dp+哈密顿回路

题意:n个点 m条边的图,路径价值定义为相邻点乘积,若路路径c[i-1]c[i]c[i+1]中c[i-1]-c[i+1]有边 则价值加上三点乘积找到价值最大的哈密顿回路,和相应的方法数n<=13.暴力dfs O(13!) TLE 由于n<13 经典的状态压缩dp [状态] [当前点位置 ][前一点位置] 注意上一个状态必须合法才能进行转移设状态dp[s][i][j] 当前状态为s,当前点为i上一个点为j的最大价值, ans=max(dp[(1<<n)-1][i])dp[s][i][

POJ_2411_Mondriaan&#39;s Dream_状态压缩dp

Mondriaan's Dream Time Limit: 3000MS   Memory Limit: 65536K Total Submissions: 15407   Accepted: 8889 Description Squares and rectangles fascinated the famous Dutch painter Piet Mondriaan. One night, after producing the drawings in his 'toilet series

动态规划之状态压缩dp入门

状态压缩动态规划(简称状压dp)是另一类非常典型的动态规划,通常使用在NP问题的小规模求解中,虽然是指数级别的复杂度,但速度比搜索快,其思想非常值得借鉴. 为了更好的理解状压dp,首先介绍位运算相关的知识. 1.'&'符号,x&y,会将两个十进制数在二进制下进行与运算,然后返回其十进制下的值.例如3(11)&2(10)=2(10). 2.'|'符号,x|y,会将两个十进制数在二进制下进行或运算,然后返回其十进制下的值.例如3(11)|2(10)=3(11). 3.'^'符号,x^y