拿到这个题,首先这个求最小和非常的简单,麻烦的是要求出最短路径。
这个真的是卡了我一阵子。本来紫书上是有解答代码的,但我想用递归去实现,所以一直也就没看书上的代码。从网上搜了搜呢,也都是书上的做法,没有创意。
但好在最终终于是想到了递归的实现方式:
首先求和很简单的dp思想,路径只要在求和的基础上简单的加一个数组来表示对于这个最一个最小行来说,下一个最小行是多少就行了。直接上代码会很容易理解:
#include<iostream>
#include<cstdio>
#include<cstring>
#include<algorithm>
using namespace std;
const int maxr=12;
const int maxc=100+10;
int m,n,p[maxr][maxc],sum[maxr][maxc],w[maxr][maxc];
int main()
{
//freopen("shuJu","w",stdout);
int slove(int,int);
while(scanf("%d%d",&m,&n)!=EOF){
for(int i=1;i<=m;i++)
for(int j=1;j<=n;j++)
scanf("%d",&p[i][j]);
memset(sum,-1,sizeof(sum));
int min_=1<<30,mi;
for(int i=1;i<=m;i++){
int t=slove(i,1);
if(t<min_){
mi=i;
min_=t;
}
}
printf("%d",mi);
mi=w[mi][1];
for(int i=2;i<=n;i++){
printf(" %d",mi);
mi=w[mi][i];
}
printf("\n%d\n",min_);
}
return 0;
}
int slove(int x,int y)
{
if(y==n)
return p[x][y];
if(sum[x][y]!=-1)
return sum[x][y];
int n1=slove(x,y+1),n2=slove(x==1?m:x-1,y+1),n3=slove(x==m?1:x+1,y+1);
sum[x][y]=min(min(n1,n2),n3)+p[x][y];
int a=0x3f3f3f3f;
if(sum[x][y]==n1+p[x][y])
a=x;
if(sum[x][y]==n2+p[x][y])
a=min(a,(x==1?m:x-1));
if(sum[x][y]==n3+p[x][y])
a=min(a,(x==m?1:x+1));
w[x][y]=a;
return sum[x][y];
}