HDU 3001 Travelling(状压DP)

来源:互联网 发布:淘宝怎么秒杀 编辑:程序博客网 时间:2024/05/29 17:04

题意:n个城市m条路,每条路有一个权值,问走遍所有城市且每个城市最多经过两次的最小费用。

思路:旅行商问题的加强版,将每一位改成三进制,注意可能有重边。

#include<cstdio>#include<cstring>#include<cmath>#include<cstdlib>#include<iostream>#include<algorithm>#include<vector>#include<map>#include<queue>#include<stack>#include<string>#include<map>#include<set>#include<ctime>#define eps 1e-6#define LL long long#define pii pair<int, int>//#pragma comment(linker, "/STACK:1024000000,1024000000")using namespace std;//const int MAXN = 5000000 + 5;const int INF = 0x3f3f3f3f;const int MAXN = 100000;int n, m, ans;int G[20][20], dp[MAXN][11], pow_3[20];void init() {pow_3[0] = 1;for(int i = 1; i <= 10; i++) pow_3[i] = pow_3[i-1] * 3;}bool check(int s) {for(int i = 0; i < n; i++) {if(!(s%3)) return false;s /= 3;}return true;}int main() {    //freopen("input.txt", "r", stdin);    init();while(cin >> n >> m) {memset(G, INF, sizeof(G));ans = INF;for(int i = 1; i <= m; i++) {int u, v, c;scanf("%d%d%d", &u, &v, &c);u--; v--;G[u][v] = G[v][u] = min(G[v][u], c);}int maxs = pow_3[n];for(int i = 0; i < maxs; i++) memset(dp[i], INF, sizeof(dp[i]));for(int i = 0; i < n; i++) {dp[pow_3[i]][i] = 0;}for(int i = 1; i < maxs; i++) {for(int j = 0; j < n; j++) if(dp[i][j]!=INF && (i/pow_3[j])%3) {if(check(i)) {ans = min(ans, dp[i][j]);continue;}else {for(int k = 0; k < n; k++) {if(G[j][k]!=INF && (i/pow_3[k])%3<2) {dp[i+pow_3[k]][k] = min(dp[i+pow_3[k]][k], dp[i][j] + G[j][k]);} }}}}if(ans == INF) cout << "-1" << endl;else cout << ans << endl;}    return 0;}



0 0
原创粉丝点击