hdu 1565 方格取数(1) 状态压缩+dp

来源:互联网 发布:食用菌的网络销售 编辑:程序博客网 时间:2024/05/30 07:13
Problem Description
给你一个n*n的格子的棋盘,每个格子里面有一个非负数。
从中取出若干个数,使得任意的两个数所在的格子没有公共边,就是说所取的数所在的2个格子不能相邻,并且取出的数的和最大。

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

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

Sample Input
375 15 21 75 15 28 34 70 5

Sample Output
188

Author
ailyanlu

Source
Happy 2007 
#include<stdio.h>
#include<string.h>
#include<iostream>
#include<algorithm>
using namespace std;


int n,k;
int Map[25][25];
int s[1<<17];
int sum[25][1<<17];
int dp[25][1<<17];


bool ok(int x)
{
    if(x&(x<<1))
        return false;
    return true;
}
void solve()
{
    int i;
    for(i=0;i<(1<<n);i++)
        if(ok(i))
            s[k++]=i;
}


int main()
{
    int i,j;
    int t;
    int r,p;
    while(scanf("%d",&n)!=EOF)
    {
        if(n==0)
        {
            printf("0\n");
            continue;
        }
        memset(s,0,sizeof(s));
        memset(sum,0,sizeof(sum));
        memset(dp,-1,sizeof(dp));
        memset(Map,0,sizeof(Map));
        for(i=0;i<n;i++)
            for(j=0;j<n;j++)
                scanf("%d",&Map[i][j]);
        k=0;
        solve();
        for(i=0;i<n;i++)
            for(j=0;j<k;j++)
                for(t=0;(1<<t)<=s[j];t++)
                {
                    if(s[j]&(1<<t))//一定是s[j],不要写成j;

                    {
                        sum[i][j]+=Map[i][t];
                    }
                }
        memcpy(dp[0],sum[0],sizeof(sum[0]));
        for(i=1;i<n;i++)
        {
            for(r=0;r<k;r++)
            {
                for(p=0;p<k;p++)
                {
                    if(s[r]&s[p])
                        continue;
                    if(dp[i-1][p]==-1)
                        continue;
                    dp[i][r]=max(dp[i][r],dp[i-1][p]+sum[i][r]);
                }
            }
        }
        int Max=0;
        for(i=0;i<k;i++)
            Max=max(dp[n-1][i],Max);
        printf("%d\n",Max);
    }
    return 0;
}
0 0
原创粉丝点击