数字三角 [SCU – 1114]
简单的动态规划,但是此题需要把路径记下来,
动态规划得从几近成功开始考虑,比如只有2的情形,只需要选两侧更大的那个即可。3层的时候就假设第2层已经知道最大收益,那就选走了第2层以及加上走第2层的收益最大的那个。每次走把当前选的是左还是右记下来,当走到最上层的时候,再反着去读走的那条路径即可。
#include <cstdio> int main(void) { int **acc,**moto; char **turnRight; int i,j,N; scanf("%d",&N); turnRight = new char* [N]; acc = new int* [N]; moto = new int* [N]; for( i=0;i<N;i++) { turnRight[i]=new char [i+1]; acc[i]=new int [i+1]; moto[i]=new int [i+1]; for(j=0;j<i+1;j++) { scanf("%d",&moto[i][j]); acc[i][j]=moto[i][j]; turnRight[i][j]=0; } } for(i=N-2;i>=0;i--) { for(j=0;j<i+1;j++) { if(acc[i+1][j]<acc[i+1][j+1]) { acc[i][j]+=acc[i+1][j+1]; turnRight[i][j]=1; } else { acc[i][j]+=acc[i+1][j]; } } } #ifdef MALICVERBOSE for(i=0;i<N;i++) { for(j=0;j<i+1;j++) { printf("%d\t",moto[i][j]); } printf("\n"); } #endif printf("%d\n",acc[0][0]); j=0; for(i=0;i<N;i++) { if(i>0) printf(" "); printf("%d",moto[i][j]); if(turnRight[i][j]==1) j+=1; } printf("\n"); for(i=0;i<N;i++) { delete [] turnRight[i]; delete [] acc[i]; } delete [] turnRight; delete [] acc; return 0; }
应该还有一个省空间的方法,对于此题,所有的数据都是正的,我们可以把turnRight[]合到数字的正负上:数字的绝对值表示数字大小,正负号表示此路是否被选中,可以省去部分内存空间。