HDU 1565 方格取数(1) 轮廓线dp
题目链接:
http://acm.hdu.edu.cn/showproblem.php?pid=1565
方格取数(1)
Memory Limit: 32768/32768 K (Java/Others)
样例输出
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-----------------------------------------------------------------------