题目描述
这是一道简单的DP题,记录路径可以用一个p数组;
设
f(i,j)
为从格子i,j出发到最右端的最小数字和。
边界是
f(n−1,j)=a(n−1,j)
我的程序n和m是反的,,,
#include<cstdio>
#include<iostream>
#include<cstring>
#include<algorithm>
#include<cstdlib>
#include<cmath>
using namespace std;
const int INF=2000000;
const int d[]={-1,0,1};
int f[200][200],a[200][200],p[200][200];
int n,m;
int main(){
while(cin>>n>>m&&n&&m){
for(int i=0;i<n;i++)
for(int j=0;j<m;j++)
scanf("%d",&a[j][i]);
for(int i=0;i<n;i++)
for(int j=0;j<m;j++)
f[j][i]=INF;
for(int i=0;i<n;i++){
f[m-1][i]=a[m-1][i];
p[m-1][i]=-1;
}
for(int i=m-2;i>=0;i--){
for(int j=0;j<n;j++){
for(int k=0;k<3;k++){
int jj=j+d[k];
if(jj<0) jj=n-1;
if(jj==n) jj=0;
if(f[i+1][jj]+a[i][j]<f[i][j]||(f[i+1][jj]+a[i][j]==f[i][j]&&jj<p[i][j])) //如果字典序更小也更新
f[i][j]=f[i+1][jj]+a[i][j],p[i][j]=jj;
}
}
}
int ans=INF,ansd;
for(int i=0;i<n;i++)
if(f[0][i]<ans) ans=f[0][i],ansd=i;
for(int i=ansd,j=0;i!=-1;i=p[j][i],j++) printf("%d%c",i+1,p[j][i]==-1?'\n':' ');
printf("%d\n",ans);
}
return 0;
}
时间复杂度 O(n2)