HDU 1565 方格取数(1) 轮廓线dp

题目链接:

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

方格取数(1)

Time Limit: 10000/5000 MS (Java/Others)
Memory Limit: 32768/32768 K (Java/Others)
#### 问题描述 > 给你一个n*n的格子的棋盘,每个格子里面有一个非负数。 > 从中取出若干个数,使得任意的两个数所在的格子没有公共边,就是说所取的数所在的2个格子不能相邻,并且取出的数的和最大。 #### 输入 > 包括多个测试实例,每个测试实例包括一个整数n 和n*n个非负数(n<=20) #### 输出 > 对于每个测试实例,输出可能取得的最大的和 ####样例输入 > 3 > 75 15 21 > 75 15 28 > 34 70 5

样例输出

188

题解

轮廓线dp,考虑每一个方格取0和取1的情况,做法和白书上的铺放骨牌差不多。

#include<map>
#include<set>
#include<cmath>
#include<queue>
#include<stack>
#include<ctime>
#include<vector>
#include<cstdio>
#include<string>
#include<bitset>
#include<cstdlib>
#include<cstring>
#include<iostream>
#include<algorithm>
#include<functional>
using namespace std;
#define X first
#define Y second
#define mkp make_pair
#define lson (o<<1)
#define rson ((o<<1)|1)
#define mid (l+(r-l)/2)
#define sz() size()
#define pb(v) push_back(v)
#define all(o) (o).begin(),(o).end()
#define clr(a,v) memset(a,v,sizeof(a))
#define bug(a) cout<<#a<<" = "<<a<<endl
#define rep(i,a,b) for(int i=a;i<(b);i++)
#define scf scanf
#define prf printf

typedef int LL;
typedef vector<int> VI;
typedef pair<int,int> PII;
typedef vector<pair<int,int> > VPII;

const int INF=0x3f3f3f3f;
const LL INFL=10000000000000000LL;
const double eps=1e-9;

const double PI = acos(-1.0);

//start----------------------------------------------------------------------

const int maxn=21;

LL dp[2][1<<maxn];

int n;
int pre,cur;

LL ans;
void update(int a,int b,LL v) {
    if(b&(1<<n)) dp[cur][b^(1<<n)]=max(dp[cur][b^(1<<n)],dp[pre][a]+v);
    ans=max(ans,dp[cur][b^(1<<n)]);
}

int main() {
    while(scf("%d",&n)==1) {
        pre=0;
        cur=1;
        clr(dp[cur],0);
        ans=0;
        rep(i,0,n) {
            rep(j,0,n) {
                LL x;
                scf("%d",&x);
                swap(pre,cur);
                clr(dp[cur],0);
                for(int k=0; k<(1<<n); k++) {
                    ///左侧和上侧都不取的时候才能取
                    if((!(k&1)||!j)&&!(k&(1<<(n-1)))) {
                        update(k,(k<<1)^1^(1<<n),x);
                    }
                    update(k,(k<<1)|(1<<n),0);
                }
            }
        }
        prf("%d\n",ans);
    }
    return 0;
}

//end-----------------------------------------------------------------------
posted @ 2016-10-25 20:13  fenicnn  阅读(121)  评论(0编辑  收藏  举报