您的位置:首页 > 其它

HDU 3001 Travelling(状压DP)

2014-12-22 19:48 381 查看
题目链接: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
; 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;
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: