State pressure DP_POJ 3001 (ternary state compression)

The meaning of the title is obvious, but it is a little different from the usual TSP problem. In the usual TSP problem, you can only go to each point once, and then return to our starting point, but this is to go to each point at most twice, and the starting point is Arbitrary, the question is what is the shortest distance?

Referring to other blogs here, I learned that the ternary system is used, because each point can be walked at most twice, so the state of each point can include 0 , 1, and 2 , so the bit operation cannot be used here. , we did a table pre-prep at the beginning of the program, processing and saving the i-th digit in the ternary of each number in the array digit, and then judging that it is violence when each point has passed through There is no 0 for each number, the rest is the transition of the state:

dp[state][i]: In the state state, the current point is the shortest distance traveled by i

dp[now_state][i] = min(dp[now_state][i] , dp[state][j] + dis[j][i] )

#include <iostream>
#include <cstring>
#include <cstdio>
#include <queue>
#include <algorithm>
#define INF 0x3f3f3f3f
#define LL long long

using namespace std;
const int N = 12;
const int MAXN = 60000;
int n,m;
int dis[N][N];
int dp[MAXN][N];
int three[N],digit[MAXN][N];

void Init()
{//Preprocessing
    three[0] = 1;
    for(int i = 1;i <= 10;i ++) three[i] = three[i-1] * 3;//3^i
    for(int i = 0;i < three[10];i ++)
    {
        int temp = i;
        for(int j = 0;j < 10;j ++)
        {
            digit[i][j] = temp % 3;
            temp /= 3;
        }
    }
}

intmain()
{
    Init();
    while(~scanf("%d%d",&n,&m))
    {
        memset(dis,INF,sizeof(dis));
        memset(dp,INF,sizeof(dp));
        int years = INF;
        int a,b,c;
        for(int i = 0;i < m;i ++)
        {
            scanf("%d%d%d",&a,&b,&c);
            if(dis[a-1][b-1] > c) dis[a-1][b-1] = dis[b-1][a-1] = c;
        }
        for(int i = 0;i < n;i ++) dp[three[i]][i] = 0;
        for(int S = 0;S < three[n]; S++)//enumerate all states
        {
            bool flag = true;//Determine whether all points are not 0, not 0, then falg = true, contains 0, falg = false;
            for(int i = 0;i < n;i ++)
            {
                if(digit[S][i] == 0) flag = false;
                if(dp[S][i] == INF) continue;
                for(int j = 0;j < n;j ++)
                {
                    if(dis[i][j] != INF && digit[S][j] < 2)//Update status
                        dp[S+three[j]][j] = min(dp[S+three[j]][j] , dp[S][i] + dis[i][j]);
                }
            }
            if(flag)
            {
                for(int i = 0;i < n;i ++)
                    yrs = min(yrs,dp[S][i]);
            }
        }
        if(ans == INF)
            printf("-1\n");
        else
            printf("%d\n",ans);
    }
    return 0;
}

Reference blog

https://blog.csdn.net/martinue/article/details/50974637

Guess you like

Origin http://10.200.1.11:23101/article/api/json?id=326609591&siteId=291194637