通过这个题目,对自顶向下分析,有了进一步的理解。题意如下表:
Vases(j) | ||||||
1 |
2 |
3 |
4 |
5 | ||
Bunches (i) |
1 |
7 |
23 |
-5 |
-24 |
16 |
2 |
5 |
21 |
-4 |
10 |
23 | |
3 |
-21 |
5 |
-4 |
-20 |
20 |
- 不同的花要出现在不同的列
- j1表示1号花放的列,依次。保证j1<j2<j3
- 最重要的,要保证三个位置上的数字和最大。
分析这个题目,首先可以得到:
- 1号花只能放在1,2,3三个位置,由1,2两个条件可得;
- 2号花只能放在2,3,4三个位置;
- 3号花只能放在3,4,5三个位置。
上面的发现,对实现算法细节很重要,如果不考虑这些,则必将是WA。下面讨论状态转移方程(我也学得越来越专业了)。首先,假设dp[i][j]表示:第i号花放在第j列的第i个位置。那么dp[i][j]值与那些有关系呢?
- 肯定是a[i][j];
- d[i - 1][j - 1]
- dp[i - 1][j - 2]
- ...
- 注意j不能够越界!!!
那么状态转移方程就为:
dp[i][j] = max(dp[i - 1][j - 1] + a[i][j], dp[i - 1][j - 2] + a[i][j], ...)
注意不要越界即可,AC代码如下:
#include
int a[101][101], dp[101][101];
int f, v;
int main() {
scanf("%d", &f);
scanf("%d", &v);
for (int i = 1; i <= f; ++i)
for (int j = 1; j <= v; ++j)
scanf("%d", &a[i][j]);
for (int i = 1; i <= f; ++i) {
dp[i][1] = 0;
}
for (int i = 1; i <= v; ++i) {
if (v - i > f - 1)
dp[1][i] = a[1][i];
else
dp[1][i] = 0;
}
for (int i = 2; i <= f; ++i) {
for (int j = i; j <= v - f + i; ++j) {
dp[i][j] = -1000;
for (int k = i - 1; k < j; ++k) {
if (dp[i - 1][k] + a[i][j] > dp[i][j])
dp[i][j] = dp[i - 1][k] + a[i][j];
}
}
}
int max = -1000;
for (int i = v - f + 1; i <= v; ++i) {
if (dp[f][i] > max) max = dp[f][i];
}
printf("%d\n", max);
return 0;
}