HDU-3001(旅行商问题+三进制状压dp)
生活随笔
收集整理的這篇文章主要介紹了
HDU-3001(旅行商问题+三进制状压dp)
小編覺得挺不錯的,現在分享給大家,幫大家做個參考.
#include <bits/stdc++.h>
using namespace std;
/*
題目大意:
給定n個點m條邊的帶權無向圖,問有沒有可能從n個點的其中一個出發,走遍其余n - 1個點,并且保證
每個點最多經過兩次,如果可以,輸出最小費用;不可以輸出-1。思路:
旅行商問題改為三進制狀壓dp。*/
typedef long long ll;
typedef pair<int, int> pii;
const int INF = 0x3f3f3f3f;
const double eps = 1e-6;
const double pi = acos(-1.0);
const int MAX_STATE = pow(3, 10);int G[10][10];
int dp[MAX_STATE][10];
int add[10];void init_add() // 預處理每一位加1需要增加的值
{int p = 1;for(int i = 0; i < 10; i++, p *= 3){add[i] = p;}
}int get_digit(int state, int digit) // 獲取當前狀態第digit位的值
{for(int i = 0; i < digit; i++){state /= 3;}return state % 3;
}int main()
{int n, m;init_add();while(scanf("%d%d", &n, &m) != EOF){memset(G, 0x3f, sizeof(G));memset(dp, 0x3f, sizeof(dp));while(m--){int u, v, w;scanf("%d%d%d", &u, &v, &w);G[u - 1][v - 1] = G[v - 1][u - 1] = min(G[u - 1][v - 1], w); // 有重邊,需要判斷重邊}int p = 1;for(int i = 0; i < n; i++, p *= 3){dp[p][i] = 0;}int ans = INF;int state = 1;for(int i = 0; i < n; i++){state *= 3; // 可能的狀態數}for(int i = 0; i < state; i++){int cnt = 0;for(int j = 0; j < n; j++){if(get_digit(i, j) == 0) continue;cnt++;for(int k = 0; k < n; k++){if(j == k) continue;if(get_digit(i, k) < 2){dp[i + add[k]][k] = min(dp[i + add[k]][k], dp[i][j] + G[j][k]);}}}if(cnt == n){for(int j = 0; j < n; j++){ans = min(ans, dp[i][j]);}}}printf("%d\n", ans == INF ? -1 : ans);}return 0;
}
總結
以上是生活随笔為你收集整理的HDU-3001(旅行商问题+三进制状压dp)的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: Qt 汽车仪表 QWidget
- 下一篇: Free Mybatis plugin插