ZOJ 3213 Beautiful Meadow(插头DP-一条路径最大值,不固定头尾)
2013-05-01 11:47
387 查看
题目链接:http://acm.zju.edu.cn/onlinejudge/showProblem.do?problemId=3396
题意:给定一个n*m的寻宝图。有些位置不能走,其余位置每个位置都有一个宝藏。从一个位置出发到另一个位置结束(这两个位置都是可以自己选择的),每个格子最多走一次。求最大价值。
思路:第一道头尾不固定的单路径。增加了一个Num,表示当前已经使用的独立插头的数目,这样只要保证num不超过2而且不合并相同的连通分量就能保证最后是一条简单路径。那么编码的时候设x表示左侧插头,y表示上面插头,x、y均存在时合并然后修改;x和y中只存在一个时或者都不存在时,在Num<2时可以考虑增加插头。
题意:给定一个n*m的寻宝图。有些位置不能走,其余位置每个位置都有一个宝藏。从一个位置出发到另一个位置结束(这两个位置都是可以自己选择的),每个格子最多走一次。求最大价值。
思路:第一道头尾不固定的单路径。增加了一个Num,表示当前已经使用的独立插头的数目,这样只要保证num不超过2而且不合并相同的连通分量就能保证最后是一条简单路径。那么编码的时候设x表示左侧插头,y表示上面插头,x、y均存在时合并然后修改;x和y中只存在一个时或者都不存在时,在Num<2时可以考虑增加插头。
#include <iostream> #include <cstdio> #include <string.h> #include <algorithm> #include <cmath> #include <vector> #include <queue> #include <set> #include <stack> #include <string> #include <map> #define max(x,y) ((x)>(y)?(x):(y)) #define min(x,y) ((x)<(y)?(x):(y)) #define abs(x) ((x)>=0?(x):-(x)) #define i64 long long #define u32 unsigned int #define u64 unsigned long long #define clr(x,y) memset(x,y,sizeof(x)) #define CLR(x) x.clear() #define ph(x) push(x) #define pb(x) push_back(x) #define Len(x) x.length() #define SZ(x) x.size() #define PI acos(-1.0) #define sqr(x) ((x)*(x)) #define FOR0(i,x) for(i=0;i<x;i++) #define FOR1(i,x) for(i=1;i<=x;i++) #define FOR(i,a,b) for(i=a;i<=b;i++) #define FORL0(i,a) for(i=a;i>=0;i--) #define FORL1(i,a) for(i=a;i>=1;i--) #define FORL(i,a,b)for(i=a;i>=b;i--) #define rush() int CC; for(scanf("%d",&CC);CC--;) #define Rush(n) while(scanf("%d",&n)!=-1) using namespace std; void RD(int &x){scanf("%d",&x);} void RD(i64 &x){scanf("%lld",&x);} void RD(u32 &x){scanf("%u",&x);} void RD(double &x){scanf("%lf",&x);} void RD(int &x,int &y){scanf("%d%d",&x,&y);} void RD(u32 &x,u32 &y){scanf("%u%u",&x,&y);} void RD(double &x,double &y){scanf("%lf%lf",&x,&y);} void RD(int &x,int &y,int &z){scanf("%d%d%d",&x,&y,&z);} void RD(u32 &x,u32 &y,u32 &z){scanf("%u%u%u",&x,&y,&z);} void RD(double &x,double &y,double &z){scanf("%lf%lf%lf",&x,&y,&z);} void RD(char &x){x=getchar();} void RD(char *s){scanf("%s",s);} void RD(string &s){cin>>s;} void PR(int x) {printf("%d\n",x);} void PR(i64 x) {printf("%lld\n",x);} void PR(u32 x) {printf("%u\n",x);} void PR(double x) {printf("%.4lf\n",x);} void PR(char x) {printf("%c\n",x);} void PR(char *x) {printf("%s\n",x);} void PR(string x) {cout<<x<<endl;} const int INF=1000000000; const int HASHSIZE=30007; const int N=200005; int n,m,code[15],cur,pre,sx,sy; int s[100][100]; int ans; struct node { int e,next ,head[HASHSIZE]; i64 cnt ,state ; void init() { clr(head,-1); e=0; } void push(i64 s,i64 val) { int i,x=s%HASHSIZE; for(i=head[x];i!=-1;i=next[i]) { if(state[i]==s) { if(val>cnt[i]) cnt[i]=val; return; } } state[e]=s; cnt[e]=val; next[e]=head[x]; head[x]=e++; } }; node dp[2]; int Num; void decode(int code[],int m,i64 st) { Num=st&7; st>>=3; int i; FORL0(i,m) code[i]=st&7,st>>=3; } i64 encode(int code[],int m) { i64 ans=0; int hash[15],i,cnt=1; clr(hash,-1); hash[0]=0; FOR0(i,m+1) { if(hash[code[i]]==-1) hash[code[i]]=cnt++; code[i]=hash[code[i]]; ans=(ans<<3)|code[i]; } ans=(ans<<3)|Num; return ans; } void update1(int i,int j) { int x,y,k,t,q=j==m?m-1:m; i64 c; FOR0(k,dp[pre].e) { decode(code,m,dp[pre].state[k]); c=dp[pre].cnt[k]; x=code[j-1]; y=code[j]; if(x&&y) { if(x!=y) { code[j-1]=code[j]=0; FOR0(t,m+1) if(code[t]==y) code[t]=x; dp[cur].push(encode(code,q),c+s[i][j]); } } else if(x||y) { if(i<n&&s[i+1][j]) { code[j-1]=x+y; code[j]=0; dp[cur].push(encode(code,q),c+s[i][j]); } if(j<m&&s[i][j+1]) { code[j-1]=0; code[j]=x+y; dp[cur].push(encode(code,q),c+s[i][j]); } if(Num<2) { Num++; code[j-1]=code[j]=0; dp[cur].push(encode(code,q),c+s[i][j]); } } else if(x==0&&y==0) { dp[cur].push(encode(code,q),c); if(i<n&&j<m&&s[i][j+1]&&s[i+1][j]) { code[j-1]=code[j]=13; dp[cur].push(encode(code,q),c+s[i][j]); } if(Num<2) { Num++; if(i<n&&s[i+1][j]) { code[j-1]=13; dp[cur].push(encode(code,q),c+s[i][j]); } if(j<m&&s[i][j+1]) { code[j]=13; dp[cur].push(encode(code,q),c+s[i][j]); } } } } } void update2(int i,int j) { int k,q=j==m?m-1:m; FOR0(k,dp[pre].e) { decode(code,m,dp[pre].state[k]); if(code[j-1]||code[j]) continue; dp[cur].push(encode(code,q),dp[pre].cnt[k]); } } i64 DP() { pre=0,cur=1; dp[0].init(); dp[0].push(0,0); int i,j; FOR1(i,n) FOR1(j,m) { dp[cur].init(); if(s[i][j]) update1(i,j); else update2(i,j); pre^=1; cur^=1; } FOR0(i,dp[pre].e) ans=max(ans,dp[pre].cnt[i]); return ans; } int main() { int C; RD(C); while(C--) { RD(n,m); int i,j; clr(s,0); ans=0; FOR1(i,n) FOR1(j,m) { RD(s[i][j]); ans=max(ans,s[i][j]); } PR(DP()); } return 0; }
相关文章推荐
- zoj 3213(插头DP 一条路径)
- 【DP】在矩阵中,选择一条从左上角到右下角、经过数字之和最大的路径
- zoj 3213 Beautiful Meadow 插头dp
- ZOJ 3213 Beautiful Meadow(插头DP)
- 插头dp模板(简单路径+一条回路+广义路径)
- ZOJ 3213 Beautiful Meadow 解题报告(插头DP)
- HDU 3377 Plan(插头DP-路径最大值)
- dp最大路径和,注意初始化,HDU
- ZOJ 3466 插头dp
- 【DP】判断在矩阵A中是否存在一条路径与数组s相同
- zoj 1074 最大子段和的推广 dp
- ZOJ 3213 Beautiful Meadow (插头DP 求简单路径)
- ZOJ 2760 How Many Shortest Path(最短路径+最大流)
- poj 2253 一条路径中的最大边 再找出最小的
- 回溯法 解决二叉树中找一条和为固定数值的路径(java)
- ZOJ 1108 FatMouse's Speed【DP】【最大上升子序列】
- LeetCode(Binary Tree Maximum Path Sum) 在二叉树中找出一条和最大的路径
- 初等dp求最大路径和,POJ1163
- hdu3377plan【哈密顿路径插头Dp】
- ZOJ 3812 We Need Medicine(dp、背包、状态压缩、路径记录)