//经典的DP,双向DP,状态转移方程为1。num[i][j]=min{num[i][j-1],num[i+1][j]}+fee[i][j]; //2。num[i][j]={num[i][j],num[i][j+1]+fee[i][j]};以上为先比较左侧与下侧,然后再和右侧 //比较来确定最终的num[i][j]的值。同时用di[i][j]确定回溯的方向。 #include<stdio.h> #include<climits> #include<string.h> int fee[105][505],num[105][505],di[105][505]; int m,n; //回溯,输出结果 int back(int x,int y) { int t1=x,t2=y; if(x==m) { printf("%d/n",y); return 0; } else { if(di[x][y]==-1) t2=y-1; else if(di[x][y]==0) t1=x+1; else t2=y+1; back(t1,t2); printf("%d/n",y); } } int main() { //freopen("mini13.in","r",stdin); //freopen("out13.txt","w",stdout); //双向DP while(scanf("%d%d",&m,&n)==2) { int i,j,k; for(i=m;i>0;i--) { for(j=1;j<=n;j++) scanf("%d",&fee[i][j]); } for(i=1;i<=n;i++) num[m][i]=fee[m][i]; int t1,t2,t3,min,t; for(i=m-1;i>=1;i--) { num[i][1]=num[i+1][1]+fee[i][1]; di[i][1]=0; for(j=2;j<=n;j++) { t1=num[i][j-1]+fee[i][j]; t2=num[i+1][j]+fee[i][j]; if(t1<t2) { num[i][j]=t1; di[i][j]=-1; } else { num[i][j]=t2; di[i][j]=0; } } for(j=n-1;j>=0;j--) { t1=num[i][j+1]+fee[i][j]; if(t1<num[i][j]) { num[i][j]=t1; di[i][j]=1; } } } //查找顶层的最小值 min=INT_MAX; for(i=1;i<=n;i++) { if(num[1][i]<min) { min=num[1][i]; t=i; } } int x=1,y=t; //输出 back(x,t); } return 0; } 另外一种查找路径 #include<stdio.h> #include<climits> #include<string.h> int fee[105][505]; int num[105][505],f[105][505]; int m,n; int main() { freopen("mini2.in","r",stdin); freopen("out2.txt","w",stdout); while(scanf("%d%d",&m,&n)==2) { int i,j; for(i=1;i<=m;i++) { for(j=1;j<=n;j++) scanf("%d",&fee[i][j]); } for(i=1;i<=n;i++) { num[1][i]=fee[1][i]; f[1][i]=i; } for(i=2;i<=m;i++) { num[i][1]=num[i-1][1]+fee[i][1]; f[i][1]=1; for(j=2;j<=n;j++) { num[i][j]=fee[i][j]; if(num[i-1][j]>num[i][j-1]) { num[i][j]+=num[i][j-1]; f[i][j]=j-1; } else { num[i][j]+=num[i-1][j]; f[i][j]=j; } } //printf("/n"); for(j=n-1;j>0;j--) { if(num[i][j+1]+fee[i][j]<num[i][j]) { num[i][j]=num[i][j+1]+fee[i][j]; f[i][j]=j+1; } } } int min=INT_MAX; for(i=1;i<=n;i++) { if(num[m][i]<min) { min=num[m][i]; j=i; } } int ans[50005],x=m,t=0; ans[0]=j; while(x!=1) { t++; ans[t]=f[x][ans[t-1]]; if(ans[t]==ans[t-1]) x--; } for(i=t;i>=0;i--) printf("%d/n",ans[i]); } return 0; }