28.旅行(UVa1347)

#include
#include
#include
using namespace std;

const int maxn = 50 + 5;
double x[maxn], y[maxn], dist[maxn][maxn], d[maxn][maxn];

int main() {
	int n;
	while (scanf("%d", &n) == 1) {
		for (int i = 1; i <= n; i++)
			scanf("%lf%lf", &x[i], &y[i]);
		for (int i = 1; i <= n; i++)
			for (int j = 1; j <= n; j++)
				// 求出两两节点的距离
				dist[i][j] = sqrt((x[i] - x[j])*(x[i] - x[j]) + (y[i] - y[j])*(y[i] - y[j]));
		/*
		d[i][j] 表示 A在i,B在j,至少需要走的距离,并且1至i全部走过。
		d[i][j] = d[j][i]
		d[i][j] 中j<=i
		边界条件:d[n - 1][j] = dist[n - 1][n] + dist[j][n]
				A 已经走到n-1还剩第n个,为最后一个,1至(1-n)已经全部走过,A已经别无选择了
				不管j在哪个节点,1至(1-n)已经全部走过,下一个节点也必然是n
		*/
		for (int i = n - 1; i >= 2; i--)
			for (int j = 1; j < i; j++) {
				if (i == n - 1) d[i][j] = dist[i][n] + dist[j][n]; // 边界条件
				else d[i][j] = min(dist[i][i + 1] + d[i + 1][j], dist[j][i + 1] + d[i + 1][i]);
				// i>=j,且1-i已经走过,不能在走,下一个不管是A走还是B走,走的节点必然是i+1
				// 选择1:A从i走到i+1,dist[i][i + 1],B不动,至少还需要走 d[i + 1][j]
				// 选择2:B从i走到i+1,dist[j][i + 1],A不动,至少还需要走 d[i][i + 1] =  d[i + 1][i]
			}
		printf("%.2lf\n", dist[1][2] + d[2][1]);
	}
	return 0;
}

你可能感兴趣的:(算法基础)