UVa116 Unidirectional TSP

        一道很容易看出状态转移的DP。一共有n*m个状态,即对应格子走到最后的最小和。需要记录路径,还需要注意n或m为1的特殊情况。


#include <iostream>    
#include <stdio.h>    
#include <cmath>    
#include <algorithm>    
#include <iomanip>    
#include <cstdlib>    
#include <string>    
#include <memory.h>    
#include <vector>    
#include <queue>    
#include <stack>    
#include <map>  
#include <set>  
#include <ctype.h>    
#define INF 1000000  
#define ll long long
#define min3(a,b,c) min(a,min(b,c))
  
using namespace std;  

int mm[12][110];
int dp[12][110];
int path[12][110];
int main(){
	int m,n;
	while(cin>>m>>n){
		for(int i=1;i<=m;i++){
			for(int j=1;j<=n;j++){
				scanf("%d",&mm[i][j]);
			}
		}
		for(int i=1;i<=m;i++){
			dp[i][n]=mm[i][n];
		}
		for(int i=n-1;i>0;i--){
			for(int j=1;j<=m;j++){
				if(j==1){
					int tmp=min3(dp[m][i+1],dp[j][i+1],dp[j+1][i+1]);
					dp[j][i]=mm[j][i]+tmp;
					if(dp[j][i+1]==tmp){
						path[j][i]=j;
					}else if(dp[j+1][i+1]==tmp){
						path[j][i]=j+1;
					}else{
						path[j][i]=m;
					}
				}else if(j==m){
					int tmp=min3(dp[j-1][i+1],dp[j][i+1],dp[1][i+1]);
					dp[j][i]=mm[j][i]+tmp;
					if(dp[1][i+1]==tmp){
						path[j][i]=1;
					}else if(dp[j-1][i+1]==tmp){
						path[j][i]=j-1;
					}else{
						path[j][i]=j;
					}
				}else{
					int tmp=min3(dp[j-1][i+1],dp[j][i+1],dp[j+1][i+1]);
					dp[j][i]=mm[j][i]+tmp;
					if(dp[j-1][i+1]==tmp){
						path[j][i]=j-1;
					}else if(dp[j][i+1]==tmp){
						path[j][i]=j;
					}else{
						path[j][i]=j+1;
					}
				}
				
			}
		}
		int ans=INF;
		int k;
		for(int i=1;i<=m;i++){
			if(dp[i][1]<ans)ans=dp[i][1],k=i;
		}
		
		if(m!=1){
			for(int i=1;i<=n;i++){
				cout<<k;
				k=path[k][i];
				if(i!=n)cout<<" ";
			}
			cout<<endl<<ans<<endl;
		}else {
			if(n==1){
				cout<<1<<endl;
				cout<<mm[1][1]<<endl;
			}else{
				int sum=0;
				for(int i=1;i<=n;i++){
					cout<<1;
					if(i!=n)cout<<" ";
					sum+=mm[1][i];
				}
				cout<<endl<<sum<<endl;
			}
		}
	}
	return 0;
}


你可能感兴趣的:(dp,uva)