题目链接:https://vjudge.net/problem/UVA-116
紫书P270
思路:dp【i】【j】定义为以(i,j)出发的路径和最小的结果。正推逆推都可。
#include<bits/stdc++.h>
using namespace std;
const int maxn = 100 + 5;
const int INF = 1000000000;
int m, n, a[maxn][maxn], d[maxn][maxn], next1[maxn][maxn];
int main()
{
int first,ans;
while(~scanf("%d%d",&m,&n))
{
memset(a,0,sizeof(a));
memset(d,0,sizeof(d));
memset(next1,0,sizeof(next1));
for(int i=0; i<m; i++)
{
for(int j=0; j<n; j++)
{
scanf("%d",&a[i][j]);
}
}
ans=INF;
first=0;
for(int j=n-1; j>=0; j--)
{
for(int i=0; i<m; i++)
{
if(j==n-1)
{
d[i][j]=a[i][j];
}
else
{
int row[]= {i,i-1,i+1};//要走的方向
if(row[1]==-1)//防止越界
{
row[1]=m-1;
}
if(row[2]==m)//防止越界
{
row[2]=0;
}
sort(row,row+3);
d[i][j]=INF;
int v;
for(int k=0; k<3; k++)
{
v=d[row[k]][j+1]+a[i][j];
if(v<d[i][j])
{
d[i][j]=v;
next1[i][j]=row[k];//记录路径
}
}
}
if(j==0&&d[i][j]<ans)
{
ans=d[i][j];
first=i;
}
}
}
printf("%d",first+1);
int i,j;
for(i=next1[first][0],j=1; j<n; i=next1[i][j],j++)
{
printf(" %d",i+1);
}
printf("\n%d\n",ans);
}
return 0;
}