日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問 生活随笔!

生活随笔

當前位置: 首頁 > 编程资源 > 编程问答 >内容正文

编程问答

HDU-3001(旅行商问题+三进制状压dp)

發布時間:2024/3/24 编程问答 49 豆豆
生活随笔 收集整理的這篇文章主要介紹了 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)的全部內容,希望文章能夠幫你解決所遇到的問題。

如果覺得生活随笔網站內容還不錯,歡迎將生活随笔推薦給好友。