首页 > 代码库 > HDU-1565 方格取数(1)

HDU-1565 方格取数(1)

             http://acm.hdu.edu.cn/showproblem.php?pid=1565                      

                                方格取数(1)

Time Limit: 10000/5000 MS (Java/Others)    Memory Limit: 32768/32768 K (Java/Others) Total Submission(s): 4740    Accepted Submission(s): 1798

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
?
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
//dp[i][j]=max(dp[i-1][k]+curline); 其中(k & j ==0)
//设dp[i][j]为取完前i行数中 第i行为二进制j状态的最大值
#include<iostream>
#include<cstdio>
#include<cstring>
using namespace std;
int n,bit[1<<21];//存储合法状态
int dp[2][1<<21];//滚动数组01之间转变。
int top,m,map[21][21];
void init()
{
    int i,t=0;
    //得到符合题意的状态数 例如: 1011 & 10110(既1011 <<1 ) =1 可得1011不符合题意
    //state[]存储每一种合法状态
    for(i=0;i<top;i++)
    {
        if(i&(i<<1))
           continue;
        else
          {
              bit[t++]=i;
          }
    }
}
int getsum(int i,int x)//状态为x
{
     int sum=0,t=0;
    while(x)
    {
        if(x&1)
           sum+=map[i][t];
       x=x>>1;
        t++;
    }
    return sum;
}
int main()
{
    int i,j,k,max,x;
  while(~scanf("%d",&n))
    {
           m=1<<n;
           
         top=1<<21;
         init();
     memset(dp,-1,sizeof(dp));
        for(i=0;i<n;i++)
         for(j=0;j<n;j++)
          scanf("%d",&map[i][j]);
        for(i=0;bit[i]<m;i++)
          dp[0][i]=getsum(0,bit[i]);//对第1行进行初始化
            for(i=1;i<n;i++) //遍历剩余数组
           {
            for(j=0;bit[j]<m;j++)//遍历所有状态
              {
                max=-9999;
              for(k=0;bit[k]<m;k++)
                //(i+1)&1无论怎么取都是0,1;
                   if(dp[(i+1)&1][k]!=-1&&(!(bit[j]&bit[k])))//保证上下不取。
                      {//遍历上一层的所有状态,求出最大值。
                          x=dp[(i+1)&1][k];
                            if(max<x)
                               max=x;
                      }
                }
                dp[i&1][j]=max+getsum(i,bit[j]);
            }
         }
         max=-9999;
         i--;
     for(k=0;bit[k]<m;k++)
      {
        if(dp[i&1][k] >max)
        max = dp[i&1][k];
      }//遍历最后一行, 找最大值
    printf("%d\n",max);
 
    }
    return 0;
}
/*
3
75 15 21
75 15 28
34 70 5
*/