题目:点击打开链接
题意:从第一行走左下,下,右下直到最后一行,输出最大路径,最大值相等输出靠右的
思路:先从上往下dp到最后一排最右边的位置,记录下来之后从该点往上找
代码:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64
#include <iostream>
#include <cstdio>
#include <cstring>
using namespace std;
int main()
{
int tt,m,n,t[105],a[105][105],dp[105][105],ans,y,k;
scanf("%d",&tt);
k=0;
while(tt--)
{
k++;
scanf("%d%d",&m,&n);
memset(dp,sizeof(dp),0);
for(int i=1;i<=m;i++)
for(int j=1;j<=n;j++)
scanf("%d",&a[i][j]);
for(int i=1;i<=n;i++)
dp[1][i]=a[1][i];
for(int i=2;i<=m;i++)
for(int j=1;j<=n;j++)
{
if(j-1>0&&j+1<=n)
dp[i][j]=min(min(dp[i-1][j-1],dp[i-1][j]),dp[i-1][j+1])+a[i][j];
else if(j-1<=0)
dp[i][j]=min(dp[i-1][j],dp[i-1][j+1])+a[i][j];
else dp[i][j]=min(dp[i-1][j],dp[i-1][j-1])+a[i][j];
}
ans=dp[m][1];
y=1;
for(int i=2;i<=n;i++)
if(ans>=dp[m][i])
{
ans=dp[m][i];
y=i;
}
t[m]=y;
for(int i=m-1;i>=1;i--)
{
if(y-1>0&&y+1<=n)
{
if(dp[i][y-1]<dp[i][y]&&dp[i][y-1]<dp[i][y+1]) {t[i]=y-1;y=y-1;continue;}
if(dp[i][y-1]>=dp[i][y]&&dp[i][y]<dp[i][y+1]) t[i]=y;
if(dp[i][y+1]<=dp[i][y]&&dp[i][y-1]>=dp[i][y+1]) {t[i]=y+1;y=y+1;continue;}
}
else if(y-1<=0)
{
if(dp[i][y]<dp[i][y+1]) t[i]=y;
if(dp[i][y+1]<=dp[i][y]) {t[i]=y+1;y=y+1;continue;}
}
else
{
if(dp[i][y-1]<dp[i][y]) {t[i]=y-1;y=y-1;continue;}
if(dp[i][y-1]>=dp[i][y]) t[i]=y;
}
}
printf("Case %d\n",k);
for(int i=1;i<m;i++) printf("%d ",t[i]);
printf("%d\n",t[m]);
}
return 0;
}