给一个矩阵,选择一条路径,使路径上的数字加和最短。
有几个要点。
1.第一行和最后一行是可以连通的。做一下判断即可。
2.状态很好想,三个可以走到map[i][j]点中最小距离。
3.要求输出路径,用数组f[]记录即可,要求字典序输出,看到别人思路是从后往前dp而且尽量选择字典序最小的路径。
3.有可能超int。用long long 。
#include <iostream>
#include <cstdio>
#include <cstring>
#include <cmath>
#include <algorithm>
using namespace std;
int map[11][101],f[11][101];
long long d[11][101];
int way(int a,int b,int c,int i)
{
int x,y,z;
x=d[a][i+1];
y=d[b][i+1];
z=d[c][i+1];
if(x<=y&&x<=z)return a;
else if(y<=x&&y<=z)return b;
return c;
}
int main(){
int m,n;
while(~scanf("%d%d",&m,&n))
{
memset(map,0,sizeof(map));
memset(d,0,sizeof(d));
for(int i=0;i<m;i++)
for(int j=1;j<=n;j++)
scanf("%d",&map[i][j]);
for(int i=n;i>=1;i--)
for(int j=0;j<m;j++)
{
int a,b,c;
if(j==0)a=0,b=1%m,c=m-1;
else if(j==m-1)a=0,b=m-2,c=m-1;
else a=j-1,b=j,c=j+1;
f[j][i]=way(a,b,c,i);
d[j][i]=d[f[j][i]][i+1]+map[j][i];
}
long long ans=1<<30;int temp=0;
for(int i=0;i<m;i++)
{
if(ans>d[i][1])
ans=d[i][1],temp=i;
}
printf("%d",temp+1);
for(int i=1;i<n;i++)
{
temp=f[temp][i];
printf(" %d",temp+1);
}
printf("\n%lld\n",ans);
}
return 0;
}