码迷,mamicode.com
首页 > 其他好文 > 详细

状态压缩DP

时间:2016-08-04 11:39:34      阅读:202      评论:0      收藏:0      [点我收藏+]

标签:

I - 方格取数(1)

Description

   给你一个n*n的格子的棋盘,每个格子里面有一个非负数。   从中取出若干个数,使得任意的两个数所在的格子没有公共边,就是说所取的数所在的2个格子不能相邻,并且取出的数的和最大。 

Input

包括多个测试实例,每个测试实例包括一个整数n 和n*n个非负数(n<=20)

Output

对于每个测试实例,输出可能取得的最大的和

Sample Input

3
75 15 21 
75 15 28 
34 70 5 

Sample Output

188

思路:

先算出一行的每个dp,然后枚举以后的每一行,他的dp就是他加上上一行中不冲突的最大的那个dp.第二道状态压缩DP,还是参照了别人的博客,写了这两个状压DP,已经对状压DP理解了很多了,下一道题可以自己做了。(下面说的C题是上一篇博客的题)

代码:

 1 #include<iostream>
 2 #include<string>
 3 #include<cstdio>
 4 #include<cmath>
 5 #include<cstring>
 6 #include<algorithm>
 7 #include<vector>
 8 #include<iomanip>
 9 #include<queue>
10 using namespace std;
11 int n,sn;
12 int dp[25][1<<13];  //这里就不需要dp[25][1<<20]了,只要能满足sn的大小就行
13 int map[25][25];
14 int sta[1<<13];
15 int max(int x,int y)
16 {
17     return x>y?x:y;
18 }
19 void init()
20 {
21     sn=0;                   //用sn代替(1<<n)表示状态会节省内存和时间,(1<<n)的方法参见C题
22     for(int i=0;i<(1<<n);i++)
23     {
24         if(i&(i<<1)) continue;
25         sta[sn++]=i;         //记录互不相邻的数
26     }
27 }
28 int insum(int a,int b)
29 {
30     int sum=0,j=n;
31     while(b)
32     {
33         if(1&b)
34         sum+=map[a][j];
35         j--;
36         b=b>>1;
37     }
38     return sum;
39 }
40 int main()
41 {
42     while(scanf("%d",&n)!=EOF)
43     {
44         memset(dp,0,sizeof(dp));
45         for(int i=1;i<=n;i++)
46         for(int j=1;j<=n;j++)
47         scanf("%d",&map[i][j]);
48         init();
49         for(int i=0;i<sn;i++)
50         dp[1][i]=insum(1,sta[i]); //这里这里直接用dp[1][i]而不是dp[1][sta[i]],会节省时间与内存
51         for(int i=2;i<=n;i++)
52         {
53             for(int j=0;j<sn;j++)
54             {
55                 int tem=insum(i,sta[j]);
56                 for(int k=0;k<sn;k++)
57                 {
58                     if((sta[j]&sta[k])) continue;  //判断与上一行状态有没有相邻的数
59                     dp[i][j]=max(dp[i][j],dp[i-1][k]+tem);
60                 }
61             }
62         }
63         int sum=0;
64         for(int i=0;i<sn;i++)
65         sum=max(dp[n][i],sum);  //最后求这一行中的最大的,因为一行中的每一个dp值
66                                 //已经加上了本行与其不相邻的数
67         printf("%d\n",sum);
68     }
69     return 0;
70 }

 

状态压缩DP

标签:

原文地址:http://www.cnblogs.com/--ZHIYUAN/p/5736030.html

(0)
(0)
   
举报
评论 一句话评论(0
登录后才能评论!
© 2014 mamicode.com 版权所有  联系我们:gaon5@hotmail.com
迷上了代码!