http://acm.pku.edu.cn/JudgeOnline/problem?id=1157
该题也是经典的动态规划,题目叙述的依然很麻烦,其实简化一下就是这样的:例如下面这个例子就是:3表示行,5表示列,然后在下面的3行5列每一行选一个数,使这3个数最大,要求选的数列数必须依次增大,就是从左上方想右下方选3个数使和最大。
3 5
7 23 -5 -24 16
5 21 -4 10 23
-21 5 -4 -20 20
我们用opt定义以当前I j为结尾的花的排序的最大值,用r*(-50)表示负无穷,初始化时第一行为origin[i][j],后面为r*(-50)
Opt[][] | 1 | 2 | 3 | 4 | 5 |
1 | 7 | 23 | -5 | -24 | 16 |
2 | -150 | -150 | -150 | -150 | -150 |
3 | -150 | -150 | -150 | -150 | -150 |
从第二行开始,对于第i行第j列,对于i>=j,遍历i-1行前j列,求出当前最大值。
Opt[][] | 1 | 2 | 3 | 4 | 5 |
1 | 7 | 23 | -5 | -24 | 16 |
2 | -150 | 21+7 | -4+max(7,23,-5) | 10+max(7,23,-5,-24) | 23+max(…) |
3 | -150 | -150 | -150 | -150 | -150 |
I=3:
Opt[][] | 1 | 2 | 3 | 4 | 5 |
1 | 7 | 23 | -5 | -24 | 16 |
2 | -150 | 28 | 19 | 33 | 46 |
3 | -150 | -150 | -4+max(-150,28) | -20+max() | 20+max(-150,28,19,33) |
最后取第i行最大值即可,核心的c代码:
for(i=2;i<=r;i++)
for(j=1;j<=c;j++)
if(j>=i)
for(k=1;k<j;k++)
if(opt[i][j]<opt[i-1][k]+origin[i][j])
opt[i][j]=opt[i-1][k]+origin[i][j];
带有详细注释的代码可以在http://download.csdn.net/user/china8848/获得