hdu 1565 方格取数(1)

方格取数(1)
Time Limit: 10000/5000 MS (Java/Others) Memory Limit: 32768/32768 K (Java/Others)
Total Submission(s): 3799 Accepted Submission(s): 1453


Problem 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


Author
ailyanlu


Source
Happy 2007


Recommend
8600

 

 1 //703MS    2056K    1378 B    C++    
 2 /*
 3     
 4     题意:
 5         中文...
 6     
 7     状态压缩:
 8         dp[i][j]表示前i行状态j的最优解
 9         先预处理出符合条件的数,17000+个(n在20以内),
10     然后进行求解,具体看注释    
11          
12 */
13 #include<stdio.h>
14 #include<string.h>
15 #define N 18000
16 int dp[25][N];
17 int g[25][25];
18 int st[N],n;
19 int Max(int a,int b)
20 {
21     return a>b?a:b;
22 }
23 int judge(int x) //预处理的判断 
24 {
25     int end=0;
26     while(x){
27         if(end && (x&1)) return 0;
28         end=x&1;
29         x>>=1;
30     }
31     return 1;
32 }
33 int main(void)
34 {
35     int K=0;
36     for(int i=0;i<(1<<20);i++)  //预处理 
37         if(judge(i)) st[K++]=i;
38     while(scanf("%d",&n)!=EOF)
39     {
40         if(n==0){
41             puts("0");continue;
42         }
43         int n0=1<<n;
44         memset(dp,0,sizeof(dp));
45         for(int i=0;i<n;i++)
46             for(int j=0;j<n;j++)
47                 scanf("%d",&g[i][j]);
48         int maxn=-1;
49         for(int i=0;st[i]<n0;i++){ //第一行先处理 
50             for(int j=0;j<n;j++){
51                 if(st[i]&(1<<j))
52                     dp[0][i]+=g[0][j];
53             }
54             maxn=Max(maxn,dp[0][i]);
55         } 
56         for(int i=1;i<n;i++){ //处理后n-1行 
57             for(int j=0;st[j]<n0;j++){  //枚举预处理出来的状态 
58                 int temp=0;
59                 for(int k=0;k<n;k++) 
60                     if(st[j]&(1<<k)) temp+=g[i][k];
61                 for(int k=0;st[k]<n0;k++)
62                     if(!(st[j]&st[k])) //符合没公共边的条件就进行比较 
63                         dp[i][j]=Max(dp[i][j],temp+dp[i-1][k]);
64                 maxn=Max(maxn,dp[i][j]);
65             }
66         }
67         printf("%d\n",maxn);
68     }
69     return 0;
70 }
71                     
72     

 

转载于:https://www.cnblogs.com/GO-NO-1/articles/3369505.html

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值