• TSP DP


      1 #include <algorithm>
      2 #include <cmath>
      3 #include <cstdio>
      4 #include <cstring>
      5 #include <deque>
      6 #include <iostream>
      7 #include <map>
      8 #include <queue>
      9 #include <set>
     10 #include <stack>
     11 #include <string>
     12 #include <vector>
     13 using namespace std;
     14 typedef long long LL;
     15 const int maxn = 18;
     16 const double PI = acos(-1);
     17 const int mod = 1e9 + 7;
     18 using namespace std;
     19 // 定义常量
     20 const int INF = 0x3f3f3f3f;
     21 #define sqr(x) ((x) * (x))
     22 // 定义变量
     23 int type; // type == 1 满秩矩阵格式, type == 2 二维坐标式
     24 int s;
     25 int N; // 城市结点数量
     26 int init_point;
     27 double dp[1 << maxn][maxn];
     28 // 动态规划状态数组dp[i][j],i表示集合V’,j表示当前到达的城市结点
     29 double dis[maxn][maxn]; // 两个城市结点之间的距离
     30 vector<int> path[1 << maxn][maxn];
     31 double ans;
     32 vector<int> ans_path;
     33 // 定义结构体
     34 struct vertex {
     35     double x, y; // 城市结点的坐标
     36     string id;   // 城市结点的id
     37     void input() {
     38         cin >> id;
     39         scanf("%lf %lf", &x, &y);
     40     }
     41 } node[maxn];
     42 
     43 double Dist(const vertex &a, const vertex &b) {
     44     return sqrt(sqr(a.x - b.x) + sqr(a.y - b.y));
     45 }
     46 
     47 void init() { // 数据初始化
     48     scanf("%d", &N);
     49     for (int i = 0; i < N; i++)
     50         node[i].input();
     51     for (int i = 0; i < N; i++) {
     52         for (int j = 0; j < N; j++)
     53             dis[i][j] = Dist(node[i], node[j]); // 计算城市之间的距离
     54     }
     55     for (int i = 0; i < (1 << N); i++) {
     56         for (int j = 0; j < N; j++)
     57             dp[i][j] = INF,path[i][j].clear();
     58     } // 初始化,除了dp[1][0],其余值都为INF
     59     ans = INF;
     60     return;
     61 }
     62 //复杂度 2^N * N^2
     63 void slove() {
     64     int M = (1 << N);
     65     // M就是第四部分所说的V’状态总数,1<<N表示2^N,总共有2^N种状态
     66     dp[1][0] = 0;
     67     path[1][0].push_back(0);
     68     // 假设固定出发点为0,从0出发回到0的花费为0。TSP只要求是一个环路,所以出发点可以任选
     69     for (int i = 1; i < M; i++) {
     70         // 枚举V’的所有状态
     71         for (int j = 1; j < N; j++) {
     72             // 选择下一个加入集合的城市
     73             if (i & (1 << j))
     74                 continue;
     75             // 城市已经存在于V’之中
     76             if (!(i & 1))
     77                 continue;
     78             // 出发城市固定为0号城市
     79             for (int k = 0; k < N; k++) {
     80                 // 在V’这个城市集合中尝试每一个结点,并求出最优解
     81                 if (i & (1 << k)) {
     82                     // 确保k已经在集合之中并且是上一步转移过来的结点
     83                     if(dp[i][k] + dis[k][j] < dp[(1 << j) | i][j]){
     84                         dp[(1 << j) | i][j] = dp[i][k] + dis[k][j];
     85                         path[(1 << j) | i][j] = path[i][k];
     86                         path[(1 << j) | i][j].push_back(j);
     87                     }
     88                     dp[(1 << j) | i][j] = min(dp[(1 << j) | i][j],
     89                                               dp[i][k] + dis[k][j]); // 转移方程
     90                 } // 将j点加入到i集合中
     91             }
     92         }
     93     }
     94     for (int i = 0; i < N; i++){
     95         if(dp[M - 1][i] + dis[i][0]< ans){
     96             ans=dp[M - 1][i] + dis[i][0];
     97             ans_path = path[M-1][i];
     98         }
     99     }
    100     // 因为固定了出发点,所以要加上到城市0的距离。另外要从所有的完成整个环路的集合V’中选择,完成最后的转移
    101 }
    102 int main() {
    103 #ifndef ONLINE_JUDGE
    104     freopen("in.txt", "r", stdin);
    105 #endif
    106     init();
    107     slove();
    108     cout<<"TSP路径长度: "<<ans<<endl<<"TSP回路: ";
    109     for(int i=0;i<ans_path.size();i++){
    110         if(i)cout<<' ';
    111         cout<<node[ans_path[i]].id;
    112     }cout<<endl;
    113     return 0;
    114 }
  • 相关阅读:
    5分钟速成C++14多线程编程
    Vue+element UI穿梭框使用
    element后台项目列表删除最后一项显示无数据
    vue+element 列表一列条件渲染
    百分比布局实现div自动换行
    store.js(一款好用的本地存储插件)的使用
    Vue开发h5或者小程序由px转换rem
    Vue中使用android和ios手机打开相机并选择相册功能和图片旋转问题
    js正则表达身份证姓名和身份证号码
    Vue中h5三个下拉框实现省级联动
  • 原文地址:https://www.cnblogs.com/jrjxt/p/12286598.html
Copyright © 2020-2023  润新知