给一个m行n列(m≤10,n≤100)的整数矩阵,从第一列任何一个位置出发每次往右、右
上或右下走一格,最终到达最后一列。要求经过的整数之和最小。整个矩阵是环形的,即第
一行的上一行是最后一行,最后一行的下一行是第一行。输出路径上每列的行号。多解时输
出字典序最小的。图9-5中是两个矩阵和对应的最优路线(唯一的区别是最后一行)。数字三角形 + 打印路径
#include<bits/stdc++.h> #define ll long long using namespace std; int m,n; int a[1000][1000]; ll dp[1000][1000]; ll INF=1e18+7; int num(int v,int n) { return (v+n)%n; } int main() { while(~scanf("%d%d",&n,&m)) { for(int i=0;i<n;i++) { for(int j=0;j<m;j++) { scanf("%d",&a[i][j]); } } for(int i=0;i<n;i++) dp[i][m-1]=a[i][m-1];//最后一列 初始化 for(int j=m-2;j>=0;j--) { for(int i=n-1;i>=0;i--) { dp[i][j]=INF; for(int k=-1;k<=1;k++) { dp[i][j]=min(dp[i][j],dp[num(i+k,n)][j+1]);//类似于数字三角形 } dp[i][j]+=a[i][j]; } } ll anss=INF; for(int i=0;i<n;i++) { anss=min(anss,dp[i][0]); } int ind=0; for(int i=0;i<n;i++) { if(dp[i][0]==anss) { ind=i;//找出字典序最小 break; } } ll ans=anss-a[ind][0]; printf("%d",ind+1); int jj=1; int ii=ind; while(jj!=m) { int b[4]; int o=0; for(int i=-1;i<=1;i++) b[o++]=num(ii+i,n); sort(b,b+4); for(int i=0;i<3;i++) { if(dp[b[i]][jj]==ans) { printf(" %d",b[i]+1) ; ii=b[i]; ans-=a[b[i]][jj];//依次找出下一个最小和所在位置 break; } } jj++; } printf("\n%lld\n",anss); } }
DP 例9-4 Unidirectional TSP
猜你喜欢
转载自blog.csdn.net/qq_43868883/article/details/103963738
今日推荐
周排行