版权声明:希望有人转(^_^) https://blog.csdn.net/Sunshine_cfbsl/article/details/52689834
好久没有做SGU了,今天来刷一道。
题目大意:
有V个花瓶
又是一道水题。。。
我的做法可能比较复杂,但还是很好理解的:
对于A数组,如下:
很容易发现有一部分是不可能用到的,如下:
所以可以转换成如下矩阵,求从(1,1)开始一条到达最后一行的路径,且每次只能往下一行横坐标不变小的位置移动,答案就是这条路径的最大权值。
然后DP一下就过了。
代码如下:
/*
ID: Sunshine_cfbsl
LANG: C++
*/
#include<cstdio>
#include<stack>
#include<algorithm>
#include<cstring>
using namespace std;
const int MAXF = 110, MAXV = 110;
const long long INF = 1LL<<62;
int f, v;
long long a[MAXF][MAXV], dp[MAXF][MAXV], ans = -INF;
stack<long long> s;
int main() {
int i, j;
scanf("%d%d", &f, &v);
for(i = 1; i <= f; i++)
for(j = 1; j <= v; j++)
scanf("%lld", &a[i][j]);
for(i = 1; i <= f; i++)
for(j = i; j <= v-f+i; j++)
a[i][j-i+1] = a[i][j];
int n = v-f+1, loc;
for(i = 1; i <= n; i++) dp[1][i] = a[1][i];
for(i = 2; i <= f; i++)
for(j = 1; j <= n; j++) dp[i][j] = -INF;
for(i = 2; i <= f; i++) {
for(j = 1; j <= n; j++) {
if(j > 1) dp[i][j] = max(dp[i][j], dp[i][j-1]-a[i][j-1]+a[i][j]);
dp[i][j] = max(dp[i][j], dp[i-1][j]+a[i][j]);
}
}
for(i = 1; i <= n; i++) {
if(dp[f][i] > ans) {
ans = dp[f][i];
loc = i;
}
}
printf("%lld\n", ans);
s.push(loc+f-1);
for(i = f; i >= 2; i--) {
if(loc > 1 && dp[i][loc] == dp[i][loc-1]-a[i][loc-1]+a[i][loc]) {
loc--;
i++;
}
else if(dp[i][loc] == dp[i-1][loc]+a[i][loc]) s.push(loc+i-2);
}
while(s.size() > 1) {
printf("%lld ", s.top());
s.pop();
}
printf("%lld\n", s.top());
return 0;
}