UVa 116 - Unidirectional TSP (dp)

题目链接:https://onlinejudge.org/index.php?option=com_onlinejudge&Itemid=8&page=show_problem&category=0&problem=52&mosmsg=Submission+received+with+ID+26597725

普通最短路径 \(dp\),但因为要输出字典序最小的方案,所以要逆推

#include<bits/stdc++.h>
using namespace std;
typedef long long ll;

const int maxn = 110;
const int INF = (1 << 30) + 1;

int n, m;
int a[maxn][maxn];
int dp[maxn][maxn], pre[maxn][maxn];

ll read(){ ll s = 0, f = 1; char ch = getchar(); while(ch < '0' || ch > '9'){ if(ch == '-') f = -1; ch = getchar(); } while(ch >= '0' && ch <= '9'){ s = s * 10 + ch - '0'; ch = getchar(); } return s * f; }

int main(){
	while(scanf("%d%d", &n, &m) == 2 && m){
		for(int i = 1 ; i <= n ; ++i){
			for(int j = 1 ; j <= m ; ++j){
				scanf("%d", &a[i][j]);
			}
		}
	
		int pos, ans = (1 << 30) + 10;
		for(int j = m ; j >= 1 ; --j){
			for(int i = 1 ; i <= n ; ++i){
				if(j == m) dp[i][j] = a[i][j];
				else{
					int row[3] = {i-1, i, i+1};
					if(i == 1) row[0] = n;
					if(i == n) row[2] = 1;
					sort(row, row + 3);
					dp[i][j] = INF;
					
					for(int k = 0 ; k <= 2 ; ++k){
						int val = dp[row[k]][j+1] + a[i][j];
						if(val < dp[i][j]){
							dp[i][j] = val; pre[i][j] = row[k];
						}
					}
				}
				if(j == 1 && dp[i][j] < ans){
					ans = dp[i][j]; pos = i;
				}
			}	
		}

		printf("%d", pos);
		for(int i = 1 ; i <= m - 1 ; ++i){
			printf(" ");
			printf("%d", pre[pos][i]);
			pos = pre[pos][i];
		} printf("\n");
		printf("%d\n", ans);
	}
	return 0;
}
posted @ 2021-07-22 00:07  Tartarus_li  阅读(30)  评论(0编辑  收藏  举报