UVa1347 Tour C++记忆化搜索

    科技2024-07-27  60

    virtualjudge地址

    题意

    1 1 1 n n n n n n个点。设计一条路线从 1 1 1开始走到 n n n,再从 n n n走回 1 1 1,除点 1 1 1经过 2 2 2次以外,其他点能且只能经过 1 1 1次。

    现给你点的个数 n n n,和每个点的横纵坐标 x i x_i xi, y i y_i yi,问在此规则下最短路径为多少?

    思路

    可以将问题看成两个人从 1 1 1出发,最终都走到 n n n的最短路,同时每个点都要被第一个人或第二个人的其中一人经过。

    所以可以设计状态为 D P ( i , j ) DP(i,j) DP(i,j)为计算两个人从第 i i i个点和第 j j j个点走到第 n n n个点的最短路程。

    s s s点是 i i i点, j j j点中进度最快的点。而由于每个点都要走过,则在第一个点到 s s s点后的每个点走过的前提下, D P ( i , j ) DP(i,j) DP(i,j)的下一个状态只能是两个人中的其中一个走到第 s s s + 1 1 1点,否则就会存在没有经过的点。然后计算继续 D P ( s + 1 , i DP(s+1,i DP(s+1,i o r or or j ) j) j)的状态, i i i o r or or j j j取决于未选择移动的是哪个的点。

    因此为了方便设计算法,我们可以将进度快的点写在前面,设点 a a a到点 b b b的距离为 d i s t [ a ] [ b ] dist[a][b] dist[a][b],就可以得出状态转移方程:

    DP(i,j) = min( DP(i+1,j) + dist[i+1][i], DP(i+1,i) + dist[i+1][j] )

    Accepted Code

    /* * @Autor: CofDoria * @Date: 2020-09-25 15:08:50 * @LastEditTime: 2020-10-07 17:44:12 */ #include <bits/stdc++.h> using namespace std; #define db double #define ll long long #define inf 0x3f3f3f3f #define s(a, n) memset(a, n, sizeof(a)) #define debug(a) cout << '#' << a << '#' << endl #define rep(l, a, b) for (register ll l = a; l < b; ++l) #define per(l, a, b) for (register ll l = a; l >= b; --l) #define _ios ios::sync_with_stdio(false), cin.tie(0), cout.tie(0) #define _forit(i, c) \ for (__typeof__((c).begin()) i = (c).begin(); i != (c).end(); ++i) bool fi = true; const unsigned long long MOD = 1e9 + 7; inline ll gcd(ll a, ll b) { return (b == 0 ? a : gcd(b, a % b)); } int n; db dp[1005][1005], dist[1005][1005]; int vis[1005][1005]; struct node { int x, y; } no[1005]; db DP(int i, int j) { if (i == n - 2) return dp[i][j] = dist[n - 1][i] + dist[n - 1][j]; if (vis[i][j]) return dp[i][j]; vis[i][j] = 1; return dp[i][j] = min(DP(i + 1, i) + dist[i + 1][j], DP(i + 1, j) + dist[i + 1][i]); } int main() { // freopen("in.txt", "r", stdin); // freopen("out.txt", "w", stdout); while (~scanf("%d", &n)) { s(vis, 0); rep(i, 0, n) scanf("%d%d", &no[i].x, &no[i].y); rep(i, 0, n - 1) { rep(j, i + 1, n) { dist[j][i] = sqrt((db)((no[j].x - no[i].x) * (no[j].x - no[i].x)) + (db)((no[j].y - no[i].y) * (no[j].y - no[i].y))); } } printf("%.2lf\n", DP(1, 0) + dist[1][0]); } // fclose(stdin); // fclose(stdout); }

    Processed: 0.013, SQL: 8