Problem Description
小茗同学正在玩牧场物语。该游戏的地图可看成一个边长为n的正方形。
小茗同学突然心血来潮要去砍树,然而,斧头在小茗的右下方。
小茗是个讲究效率的人,所以他会以最短路程走到右下角,然后再返回到左上角。并且在路上都会捡到/踩到一些物品,比如说花朵,钱和大便等。
物品只能被取最多一次。位于某个格子时,如果格子上还有物品,就一定要取走。起点和终点上也可能有物品。
每种物品我们将为其定义一个价值,当然往返之后我们取得的物品的价值和越大越好。但是小茗同学正在认真地玩游戏,请你计算出最大的价值和。
Input
多组数据(<=10),处理到EOF。
第一行输入正整数N(N≤100),表示正方形的大小。
接下来共N行,每行N个整数Ai,j(|Ai,j|≤10^9),表示相应对应位置上物品的价值。值为0表示没有物品。
Output
每组数据输出一个整数,表示最大价值和。
Sample Input
Sample Output
1 #include2 #include 3 #include 4 #include 5 #include 6 using namespace std; 7 const int MAXN = 107; 8 typedef long long ll; 9 ll dp1[MAXN][MAXN], dp2[MAXN][MAXN]; 10 ll a[MAXN][MAXN], path[MAXN][MAXN]; 11 12 void update(int x, int y) 13 { 14 if (x <= 0 || y <= 0) return; 15 a[x][y] = 0; 16 if (path[x][y] == 0) { 17 update(x - 1, y); 18 } 19 else if (path[x][y] == 1) { 20 update(x, y - 1); 21 } 22 else return; 23 } 24 25 int main() 26 { 27 int N; 28 while (cin >> N) 29 { 30 for (int i = 1; i <= N; i++) 31 for (int j = 1; j <= N; j++) 32 cin >> a[i][j]; 33 memset(path, -1, sizeof(path)); 34 memset(dp1, 0, sizeof(dp1)); 35 memset(dp2, 0, sizeof(dp2)); 36 for (int i = 1; i <= N; i++) 37 for (int j = 1; j <= N; j++) 38 { 39 if (dp1[i - 1][j] > dp1[i][j - 1]) { 40 dp1[i][j] = a[i][j] + dp1[i - 1][j]; 41 path[i][j] = 0; 42 } 43 else 44 { 45 dp1[i][j] = a[i][j] + dp1[i][j - 1]; 46 path[i][j] = 1; 47 } 48 } 49 a[N][N] = 0; 50 a[1][1] = 0; 51 update(N, N); 52 for (int i = N; i >= 1; i--) 53 for (int j = N; j >= 1; j--) 54 dp2[i][j] = a[i][j] + max(dp2[i + 1][j], dp2[i][j + 1]); 55 cout << dp1[N][N] + dp2[1][1] << endl; 56 } 57 return 0; 58 }
或者,我想难道是这个方法有漏洞?
后来,我看了好多网上的博客,感觉大牛们的想法出奇的一致!:可以把问题转化成两个人同时走。两个人同时走?我一个人来回走就不行????,谁让别人写的都是对的呢。。
思路就是用dp[k][x1][y1][x2][y2]表示俩人走第k步时的状态。空间复杂度高,易发现k+2=x+y,所以只记录k,x,优化掉y:dp[k][x1][x2],还不满意,感觉还高,由于本层状态只和上一层有关,所以用滚动数组,k只取0、1就好。dp[k][i][j]=max(dp[k^1][i][j],dp[k^1][i-1][[j-1],dp[k^1][i-1][j],dp[k^1][i][j-1])。(A下B下,A下B右,A右B下,A右B右四种情况转移)。
1 #include2 #include 3 #include 4 using namespace std; 5 typedef long long ll; 6 const ll INF=1e12; 7 const int MAXN=107; 8 ll dp[2][MAXN][MAXN]; 9 ll a[MAXN][MAXN]; 10 int N; 11 12 int main() 13 { 14 while(cin>>N)//多组数据多组数据!!!竟然还再这里WA 15 { 16 for(int i=0;i<=N;i++) 17 for(int j=0;j<=N;j++){ 18 dp[0][i][j]=dp[1][i][j]=-INF; 19 if(i>0&&j>0) 20 cin>>a[i][j]; 21 } 22 dp[0][1][1]=a[1][1]; 23 int c,k; 24 for(c=0,k=1;k<=2*N-2;k++) 25 { 26 c^=1; 27 for(int i=1;i<=N;i++) 28 for(int j=1;j<=N;j++){ 29 dp[c][i][j]=max(max(dp[c^1][i][j],dp[c^1][i-1][j-1]),max(dp[c^1][i-1][j],dp[c^1][i][j-1])); 30 if(i==j) 31 dp[c][i][j]+=a[i][k+2-i]; 32 else 33 dp[c][i][j]+=a[i][k+2-i]+a[j][k+2-j]; 34 } 35 } 36 cout< endl; 37 } 38 return 0; 39 }
当然,也有人写记忆化写对的,但我一写就错。。。。
1 #include2 #include <string.h> 3 #include <string> 4 #include 5 #include 6 using namespace std; 7 #define LL long long 8 #define lson l,m,rt<<1 9 #define rson m+1,r,rt<<1|1 10 #define lowbit(x) (x&-x) 11 12 const int maxn = 105; 13 const LL INF = 1e15+7; 14 15 int n; 16 LL dp[maxn][maxn][2*maxn],a[maxn][maxn]; 17 bool vis[maxn][maxn][2*maxn]; 18 int d[] = {0,1}; 19 20 LL dfs(int x0,int y0,int x1,int y1,int t) 21 { 22 if(t>=2*n-1) return 0; 23 if(x0<1||x0>n||x1<1||x1>n) return -INF; 24 if(y0<1||y0>n||y1<1||y1>n) return -INF; 25 26 if(vis[x0][x1][t]) return dp[x0][x1][t]; 27 vis[x0][x1][t] = true; 28 29 LL mx = -INF; 30 mx = max(mx,dfs(x0,y0+1,x1,y1+1,t+1)); 31 mx = max(mx,dfs(x0,y0+1,x1+1,y1,t+1)); 32 mx = max(mx,dfs(x0+1,y0,x1,y1+1,t+1)); 33 mx = max(mx,dfs(x0+1,y0,x1+1,y1,t+1)); 34 35 dp[x0][x1][t] = mx; 36 if(x0==x1&&y0==y1) dp[x0][x1][t] += a[x0][y0]; 37 else dp[x0][x1][t] += a[x0][y0]+a[x1][y1]; 38 39 return dp[x0][x1][t]; 40 } 41 42 int main() 43 { 44 while(scanf("%d",&n)!=EOF) 45 { 46 for(int i=1; i<=n; i++) 47 for(int j=1; j<=n; j++) 48 cin>>a[i][j]; 49 memset(vis,0,sizeof(vis)); 50 dfs(1,1,1,1,0); 51 cout< 1][1][0]<<endl; 52 } 53 return 0; 54 }
参考博客(感谢~):
【1】:http://blog.csdn.net/qq1059752567/article/details/62884319
【2】:http://blog.csdn.net/tc_to_top/article/details/51567063
【3】:http://blog.csdn.net/queuelovestack/article/details/51296950
【4】:http://m.blog.csdn.net/Tc_To_Top/article/details/51567063
【5】:http://blog.csdn.net/mengxiang000000/article/details/72851519