题解:dp[ i ][ j ]表示从格子(i,j)出发到最后一列的最小开销。
以前看这道题,感觉不太好写。其思路有点像数字三角行,从后往前推,不过这道题还要处理很多细节,一是初始化,二是方向的问题 ,因为图是环形的,
三是记录路径(长知识了)。
代码摘自紫书
1 #include<cstdio> 2 #include<cstring> 3 #include<iostream> 4 #include<algorithm> 5 #define INF 1e8 6 using namespace std; 7 typedef long long ll; 8 9 int m,n; 10 int map[200][200],dp[200][200]; 11 12 void solve() 13 { int ans=INF,first=0,next[200][200]; 14 15 for(int j=n-1;j>=0;j--){ 16 for(int i=0;i<m;i++){ 17 if(j==n-1) dp[i][j]=map[i][j]; 18 else{ 19 int d[3]={i,i-1,i+1}; 20 if(i==0) d[1]=m-1; 21 if(i==m-1) d[2]=0; 22 sort(d,d+3); //重新排序,以便找到最小的字典序。 23 24 dp[i][j]=INF; 25 for(int k=0;k<3;k++){ 26 int v=dp[d[k]][j+1]+map[i][j]; 27 if(v<dp[i][j]) { dp[i][j]=v; next[i][j]=d[k]; } 28 } 29 } 30 if(j==0&&dp[i][j]<ans) { ans=dp[i][j]; first=i; } 31 } 32 } 33 34 printf("%d",first+1); 35 for(int i=next[first][0],j=1;j<n;i=next[i][j],j++) printf(" %d",i+1); 36 printf(" %d ",ans); 37 } 38 39 int main() 40 { while(cin>>m>>n){ 41 for(int i=0;i<m;i++) 42 for(int j=0;j<n;j++) 43 cin>>map[i][j]; 44 solve(); 45 } 46 return 0; 47 }