HDU3001&BUCU * * * * - traveling 2 (English version) - problem solution

Posted by ysu on Sun, 23 Jan 2022 03:36:32 +0100

Traveling salesman deformation 2

Time limit: 3 seconds
Space limit: 256M

Title Description

Sanli akaman Decided to visit n n n cities. It wants to visit all cities. It doesn't mind which city is her starting point.

have m m m roads charge as usual, but she doesn't want to go to a city 2 2 Twice. I want to minimize the cost.

Enter description

The input includes several test cases.

For each test case:

The first line contains two integers n ( 1 ≤ n ≤ 10 ) n(1\leq n\leq10) n(1 ≤ n ≤ 10) and m m m. Show n n n cities m m m roads.

next m m m lines, each line contains three integers a , b a,b a. b and c ( 1 ≤ a , b ≤ n ) c(1\leq a, b\leq n) c(1 ≤ a,b ≤ n), expressed in a a a and b b b there is a road between them, and the cost is c c c

Output description

For each test case, the minimum fee to be paid for single line output.

If such a route cannot be found, output − 1 -1 −1.

Example 1

input

2 1
1 2 100
3 2
1 2 40
2 3 50
3 3
1 2 3
1 3 4
2 3 10

output

100
90
7

Topic analysis

This problem is a deformation of the traveling salesman problem. Rehe city can be used as the source point, and you can walk through each city without going back to the source point.

Each city can go through at most twice and at least once to find the minimum cost of all cities.

In this problem, each city has three states, which can be expressed in ternary system (0 means not visited, 1 means visited once, and 2 means visited twice)

Problem solving ideas

There are at most 10 cities in this question, each of which has 3 values in total 3 10 = 59050 3^{10}=59050 310 = 59050 states.

For example, there are five cities, ( 11202 ) 3 (11202)_3 (11202) 3 , indicates that the first city has been visited twice, the second city has been visited 0 times, the third city has been visited 2 times, and the fourth and fifth cities have been visited once respectively.

Status indication: dp[S][u] indicates the minimum cost of accessing all remaining cities by dividing from u when the current status is s.

State transition equation: DP [S] [u] is equal to the minimum cost of accessing all remaining cities from v when the state is s - {u}, plus the boundary value from u to v. If u has multiple unreachable adjacency points V, its minimum value is taken. dp[S][u]=min(dp[S][u], dp[S-{u}][v]+d[u][v])

Boundary condition: DP [tri[i] [i] = 0. When the initialization status is tri[i], the minimum cost starting from I is 0.

tri[i] indicates that the ith node has been accessed once and other nodes have not been accessed. Bit I of the ternary number represented by tri[i] is 1, and other bits are 0 tri[i] can be represented by an array, which means ternary, but it is assigned to decimal in this program. For example, the third bit of the ternary number represented by tri[3] is 1, and the other bits are 0, i.e ( 100 ) 3 (100)_3 (100) 3, its corresponding decimal number ( 100 ) 3 = 1 × 3 2 + 0 × 3 1 + 0 × 3 0 = 9 (100)_3=1\times3^2+0\times3^1+0\times3^0=9 (100)3​=1×32+0×31+0×30=9, t r i [ 3 ] = 9 tri[3]=9 tri[3]=9. Do the same for other nodes to get the array int tri[12]={0, 1, 3, 9, 27, 81, 243, 729, 2187, 19683, 59048}.

dp[9][3] indicates the minimum cost of completing the remaining cities from 3 when only the third city has been visited.

AC code

#include <bits/stdc++.h>
using namespace std;
#define mem(a) memset(a, 0, sizeof(a))
#define dbg(x) cout << #x << " = " << x << endl
#define fi(i, l, r) for (int i = l; i < r; i++)
#define cd(a) scanf("%d", &a)
typedef long long ll;

int dig[60000][11];
int dp[60000][11];
int tri[12];
int edge[11][11];

void init() {
    tri[1] = 1;
    for (int i = 2; i < 12; i++)
        tri[i] = tri[i - 1] * 3;
    for (int i = 0; i < 59050; i++) { // Bit j of preprocessing state S
        int t = i;
        for (int j = 1; j <= 10; j++) {
            dig[i][j] = t % 3;
            t /= 3;
            if (!t)
                break;
        }
    }
}

int main() {
    init();
    int n, m;
    while (cin >> n >> m) {
        for (int i = 0; i <= tri[n + 1]; i++) 
            for (int j = 0; j <= n; j++)
                dp[i][j] = 1e8;
        for (int i = 1; i <= n; i++)
            dp[tri[i]][i] = 0;
        for (int i = 1; i <= n; i++)
            for (int j = 1; j <= n; j++)
                edge[i][j] = 1e8;
        while (m--) {
            int u, v, c;
            scanf("%d%d%d", &u, &v, &c);
            edge[u][v] = edge[v][u] = min(edge[u][v], c);
        }
        int ans = 1e8;
        for (int S = 0; S < tri[n + 1]; S++) {
            bool visit_all = true;
            for (int u = 1; u <= n; u++) {
                if (dig[S][u] == 0) {
                    visit_all = false;
                    continue;
                }
                for (int v = 1; v <= n; v++) {
                    if (dig[S][v] == 0)
                        continue;
                    dp[S][u] = min(dp[S][u], dp[S - tri[u]][v] + edge[u][v]);
                }
            }
            if (visit_all)
                for (int u = 1; u <= n; u++)
                    {
                        ans = min(ans, dp[S][u]);
                        if (ans < -5)
                            ans++;
                    }
        }
        cout << ans << endl;
    }
    return 0;
}

Original is not easy, please attach the reprint Original link Oh~
Tisfy: https://letmefly.blog.csdn.net/article/details/122634759

Topics: Dynamic Programming Graph Theory