题意:给你一个n*m的矩阵,每一行取出一个数,使得这些数和最小,且相邻两行的数所在的列的差的绝对值不能超过1。如果不止一种取法,输出列序号最大的。
分析:数塔DP= =。。多了一个数组来记录每一个节点的后继。。。因为要从上往下输出,所以我们从下往上递推,这样可以避免递归输出路径。。。注意要优先选取靠右的列。。。
#include<stdio.h>
#include<stdlib.h>
#include<math.h>
#include<string.h>
#include<iostream>
#include<map>
#include<set>
#include<algorithm>
#include<queue>
#include<vector>
#include<time.h>
using namespace std;
int a[105][105];
int dp[105][105];
int pre[105][105];
int main()
{
int n,m,t,ca=0;
scanf("%d",&t);
while(t--)
{
scanf("%d%d",&n,&m);
memset(a,0,sizeof(a));
memset(dp,0,sizeof(dp));
memset(pre,0,sizeof(pre));
for(int i=1;i<=n;i++){
a[i][0]=a[i][m+1]=1<<30;
dp[i][0]=dp[i][m+1]=1<<30;
for(int j=1;j<=m;j++)
scanf("%d",&a[i][j]);
}
for(int i=1;i<=m;i++)
dp[n][i]=a[n][i];
for(int i=n-1;i>=1;--i)
for(int j=1;j<=m;j++){
dp[i][j]=dp[i+1][j+1],pre[i][j]=j+1;
if(dp[i][j]>dp[i+1][j])
dp[i][j]=dp[i+1][j],pre[i][j]=j;
if(dp[i][j]>dp[i+1][j-1])
dp[i][j]=dp[i+1][j-1],pre[i][j]=j-1;
dp[i][j]+=a[i][j];
}
int ans=dp[1][m],ans1=m;
for(int i=m-1;i>=1;--i)
if(ans>dp[1][i])
ans=dp[1][i],ans1=i;
printf("Case %d\n",++ca);
printf("%d",ans1);
for(int i=2;i<=n;i++)
{
ans1=pre[i-1][ans1];
printf(" %d",ans1);
}
puts("");
}
return 0;
}