水题。
从左和上到右扫一遍,在从右到左扫一遍,记录下最小的值和路径。path[i][j]记录是从哪个方向转移的。这样就ok了~
代码如下:
#include<iostream>
#include<cstdio>
#include<cstring>
#include<algorithm>
using namespace std;
#define INF 1e13
int M,N;
int map[111][555];
__int64 dp[111][555];
int path[111][555];
int p[50000];
void init()
{
int i,j;
for(i=0;i<=N+1;i++)
{
dp[0][i]=INF;
}
for(i=0;i<=M+1;i++)
{
dp[i][0]=INF;
dp[i][N+1]=INF;
}
for(i=1;i<=N;i++)
{
dp[1][i]=map[1][i];
path[1][i]=1;
}
}
void DP()
{
int i,j;
for(i=2;i<=M;i++)
{
for(j=1;j<=N;j++)
{
if(dp[i][j-1]<dp[i-1][j])
{
dp[i][j]=map[i][j]+dp[i][j-1];
path[i][j]=2;
}
else
{
dp[i][j]=map[i][j]+dp[i-1][j];
path[i][j]=1;
}
//dp[i][j]=map[i][j]+Min(dp[i][j-1],dp[i-1][j]);
}
for(j=N;j;j--)
{
if(dp[i][j]>map[i][j]+dp[i][j+1])
{
dp[i][j]=map[i][j]+dp[i][j+1];
path[i][j]=3;
}
}
}
}
void print()
{
int i,j,posi,posj;
__int64 Min=INF;
for(i=1;i<=N;i++)
{
if(dp[M][i]<Min)
{
Min=dp[M][i];
posi=M;
posj=i;
}
}
int len=0;
p[len++]=posj;
while(path[posi][posj])
{
if(path[posi][posj]==1)
{
p[len++]=posj;
posi--;
}
if(path[posi][posj]==2)
{
posj--;
p[len++]=posj;
}
if(path[posi][posj]==3)
{
posj++;
p[len++]=posj;
}
}
for(len-=2;len>=0;len--)
{
printf("%d\n",p[len]);
}
}
int main()
{
int i,j;
scanf("%d%d",&M,&N);
for(i=1;i<=M;i++)
{
for(j=1;j<=N;j++)
{
scanf("%d",&map[i][j]);
}
}
init();
DP();
print();
return 0;
}