UVA - 116 Unidirectional TSP 多段图的最短路 dp

题意

分析

因为字典序最小,所以从后面的列递推,每次对上一列的三个方向的行排序就能确保,数字之和最小DP就完事了

代码

因为有个地方数组名next和里面本身的某个东西冲突了,所以编译错了,后来改成nt就过了

#include<iostream>
#include<string.h>
#include<algorithm>
using namespace std;
const int inf=0x3f3f3f3f;
int a[110][110];//矩阵元素数据
int dp[110][110];//记录该位置到最后一列的最小数字总和
int nt[110][110];//next[i][j]该位置j-1列行号最小值
int main(){
	
	int n,m,i,j;
   //freopen("in.txt","r",stdin);
	while(cin>>m>>n){

		for(i=0;i<m;i++)
		for(j=0;j<n;j++)
		cin>>a[i][j];
		
		int ans=inf,first=0;
		
		for(j=n-1;j>=0;j--){
			
			for(i=0;i<m;i++){
				
				if(j==n-1) dp[i][j]=a[i][j];
				
				else{
					int row[3]={i,i-1,i+1};//右边行不变,右上行减一,右下行加一 
					if(i==0) row[1]=m-1;//处理特殊情况 
					if(i==m-1) row[2]=0;
					sort(row,row+3);//这样排序确保字典序最小
					 dp[i][j]=inf;
					 //动态规划了
					 for(int k=0;k<3;k++){
					 	int v=dp[row[k]][j+1]+a[i][j];
					 	if(dp[i][j]>v){
					 		
					 		dp[i][j]=v;
					 		nt[i][j]=row[k];
						 }
					 } 
				}
				if(j==0&&ans>dp[i][j]){
					ans=dp[i][j];
					first=i;
				}
			}
		}
	cout<<first+1;//输出第一列
            for(int j=nt[first][0],i=1;i<n;j=nt[j][i],i++)//输出其他列
                cout<<" "<<j+1;
            cout<<endl;
            cout<<ans<<endl;
	}
	return 0;
} 
posted @ 2018-10-17 11:30  ChunhaoMo  阅读(105)  评论(0编辑  收藏  举报