1. 程式人生 > >hdu 1565 方格取數(狀壓dp)

hdu 1565 方格取數(狀壓dp)

給你一個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
#include<iostream>
#include<cstdio>
#include<cstring>
#include<algorithm>
#define maxn 20000
int dp[25][maxn], sta[maxn];

int a[25][25];
int n,cnt;
using namespace std;

void init()
{cnt=0;

    for(int i=0;i<(1<<n);i++)
    {
        if(i&(i<<1))
        continue;
        sta[cnt++]=i;
    }
}
int main()
{
    while(~scanf("%d",&n))
    {memset(dp,0,sizeof(dp));
    memset(sta,0,sizeof(sta));
        init();
        int ans=0;
        for(int i=0;i<n;i++)
        for(int j=0;j<n;j++)
        scanf("%d",&a[i][j]);
        for(int i=0;i<cnt;i++)
        for(int j=0;j<n;j++)
        {
            if((sta[i]&(1<<j))>0)
               dp[0][i]+=a[0][j];
               if(dp[0][i]>ans)
               ans=dp[0][i];
        }
        for(int i=1;i<n;i++)
        for(int j=0;j<cnt;j++)
        {
            for(int k=0;k<cnt;k++)
            if((sta[j]&sta[k])==0)
            dp[i][j]=max(dp[i][j],dp[i-1][k]);
            for(int k=0;k<n;k++)
            if((sta[j]&(1<<k))>0)
            dp[i][j]+=a[i][k];
            if(ans<dp[i][j])
            ans=dp[i][j];
        }
        printf("%d\n",ans);
    }
    return 0;
}