码迷,mamicode.com
首页 > 编程语言 > 详细

FZU 2234 牧场物语【多线程dp】

时间:2017-08-20 16:49:33      阅读:202      评论:0      收藏:0      [点我收藏+]

标签:处理   ref   返回   date   none   stream   family   定义   png   

技术分享 Problem 2234 牧场物语

技术分享 Problem Description

小茗同学正在玩牧场物语。该游戏的地图可看成一个边长为n的正方形。

小茗同学突然心血来潮要去砍树,然而,斧头在小茗的右下方。

技术分享

小茗是个讲究效率的人,所以他会以最短路程走到右下角,然后再返回到左上角。并且在路上都会捡到/踩到一些物品,比如说花朵,钱和大便等。

技术分享

 

物品只能被取最多一次。位于某个格子时,如果格子上还有物品,就一定要取走。起点和终点上也可能有物品。

每种物品我们将为其定义一个价值,当然往返之后我们取得的物品的价值和越大越好。但是小茗同学正在认真地玩游戏,请你计算出最大的价值和。

技术分享 Input

多组数据(<=10),处理到EOF。

第一行输入正整数N(N≤100),表示正方形的大小。

接下来共N行,每行N个整数Ai,j(|Ai,j|≤10^9),表示相应对应位置上物品的价值。值为0表示没有物品。

技术分享 Output

每组数据输出一个整数,表示最大价值和。

技术分享 Sample Input

2 11 14 16 12

技术分享 Sample Output

53
 
题意自明,本来想的是直接先dp一遍,先求个最大值,再标记走过的点为0,倒着回去再dp一遍,再求个最大值,两个最大值一加就好了。但一直WA。不知道这算不算记忆化,不知道哪里写错了。也请过路大牛指教:
技术分享
 1 #include<iostream>
 2 #include<cstdio>
 3 #include<cmath>
 4 #include<cstring>
 5 #include<algorithm>
 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 }
WA了

或者,我想难道是这个方法有漏洞?

后来,我看了好多网上的博客,感觉大牛们的想法出奇的一致!:可以把问题转化成两个人同时走。两个人同时走?我一个人来回走就不行?????,谁让别人写的都是对的呢。。

思路就是用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 #include<iostream>
 2 #include<cstdio>
 3 #include<cstring>
 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<<dp[c][N][N]<<endl;
37     }
38     return 0;
39 }
Reference Code

 

 

 

FZU 2234 牧场物语【多线程dp】

标签:处理   ref   返回   date   none   stream   family   定义   png   

原文地址:http://www.cnblogs.com/zxhyxiao/p/7400280.html

(0)
(0)
   
举报
评论 一句话评论(0
登录后才能评论!
© 2014 mamicode.com 版权所有  联系我们:gaon5@hotmail.com
迷上了代码!