Timus 1029
简单的一道DP,只不过是每个状态与三个子状态有关,令res[i][j]表示从第一层到达map[i][j]的最小费用。
本应该res[i][j]=min(res[i-1][j],res,[i][j+1],res[i][j-1])+map[i][j];但是在res[i][j+1]是在res[i][j]求出来之后才求出来,那我们怎么办呢?我们可以这样处理:每一行正反各求一次取最小值。
#include<iostream>
#include<cstdio>
#include<cstring>
#include<stack>
using namespace std;
#define MAX 1234567890
int map[110][510],res[110][510];
stack <int> S;
int min(int a,int b)
{
return a < b ? a : b;
}
int work(int n,int m)
{
int i,j,Min,Min_i;
for(i=1;i<=m;i++) res[1][i]=map[1][i];
for(i=2;i<=n;i++)
{
for(j=1;j<=m;j++)
res[i][j]=min(res[i-1][j],res[i][j-1])+map[i][j];
for(j=m;j>=1;j--)
res[i][j]=min(res[i][j],min(res[i-1][j],res[i][j+1])+map[i][j]);
}
Min=MAX;
for(i=1;i<=m;i++)
if(Min > res[n][i]) { Min=res[n][i]; Min_i=i;}
return Min_i;
}
int print(int k,int n)
{
int i,j;
i=n; j=k; S.push(k);
while(i>1)
{
if(res[i][j-1]+map[i][j]==res[i][j])
{
S.push(j-1); j=j-1;
}
else if(res[i][j+1]+map[i][j]==res[i][j])
{
S.push(j+1); j=j+1;
}
else if(res[i-1][j]+map[i][j]==res[i][j])
{
S.push(j); i=i-1;
}
}
printf("%d",S.top()); S.pop();
while(!S.empty())
{
printf(" %d",S.top()); S.pop();
}
printf("\n");
return 0;
}
int main()
{
int i,j,m,n;
while(scanf("%d %d",&n,&m)!=EOF)
{
for(i=1;i<=n;i++)
for(j=1;j<=m;j++)
scanf("%d",&map[i][j]);
for(i=1;i<=n;i++) res[i][0]=res[i][m+1]=MAX;
print(work(n,m),n);
}
return 0;
}