HDU 3001 Travelling(状压DP)

来源:互联网 发布:电脑mac是什么意思 编辑:程序博客网 时间:2024/05/29 16:58

题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=3001


题意:和旅行商类似,就是起点不固定,而且每个城市最多走两次,求能经过每个城市最小权值和


思路:类似TSP的状压方法,改用三进制进行DP,每一位代表经过该点的次数


#include <cstdio>#include <cstring>#include <iostream>#include <algorithm>#include <queue>#include <vector>using namespace std;const int inf = 0x3f3f3f3f;const int maxn = 60000;int st[15];int dp[maxn][15];int vis[maxn][15];int dis[15][15];int n, m;void init(){    st[0] = 1;    for(int i = 1; i <= 10; i++)        st[i] = st[i - 1] * 3;    for(int i = 0; i <= st[10]; i++)    {        int k = i;        for(int j = 0; j <= 10; j++)        {            vis[i][j] = k % 3;            k /= 3;        }    }}int main(){       init();    while(~scanf("%d%d", &n, &m))    {        memset(dp, inf, sizeof(dp));        memset(dis, inf, sizeof(dis));        for(int i = 0; i < n; i++)            dp[st[i]][i] = 0;        while(m--)        {            int u, v, w;            scanf("%d%d%d", &u, &v, &w);            u--, v--;            dis[u][v] = dis[v][u] = min(dis[u][v], w);        }        int ans = inf;        for(int s = 0; s < st[n]; s++)                  //类似“我为人人”的推法        {            int flag = 1;            for(int u = 0; u < n; u++)            {                if(!vis[s][u]) flag = 0;                if(dp[s][u] == inf) continue;           //剪枝                for(int v = 0; v < n; v++)                {                    if(u != v &&  vis[s][v] < 2)                    {                        dp[s + st[v]][v] = min(dp[s + st[v]][v], dp[s][u] + dis[u][v]);                    }                }            }            if(flag)            {                for(int i = 0; i < n; i++)                    ans = min(ans, dp[s][i]);            }        }        if(ans == inf)            puts("-1");        else            printf("%d\n", ans);    }    return 0;}




0 0
原创粉丝点击