• hdu3001_三进制状压dp


    题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=3001

    题意:n个城市, 每个城市最多去两次,起点任意,问需要的最少旅费是多少?

      1 #include <iostream>
      2 #include <cstdio>
      3 #include <cstring>
      4 #include <algorithm>
      5 #include <cstdlib>
      6 #include <cmath>
      7 #include <set>
      8 #include <map>
      9 #include <queue>
     10 #include <vector>
     11 #define INF 0x3f3f3f3f
     12 using namespace std;
     13 
     14 const int N = 10, M = 60100;
     15 int dp[M][N];
     16 int num[11][11], ab[11];
     17 int n, m, f[M][N];
     18 void find()
     19 {
     20     ab[0] = 1;
     21     for(int i = 1; i <= 10; ++i)
     22         ab[i] = 3 * ab[i - 1];
     23     for(int i = 0; i < M; i++)
     24     {
     25         int te = i;
     26         for(int j = 0; j < N; j++)
     27         {
     28             f[i][j] = te % 3;
     29             te /= 3;
     30         }
     31     }
     32 }
     33 int rec()
     34 {
     35     int sum = ab[n];
     36     for(int i = 0; i < sum; ++i)
     37         for(int j = 0; j < n; ++j)
     38             dp[i][j] = INF;
     39     for(int i = 0; i < n; i++)
     40         dp[ab[i]][i] = 0;
     41     for(int i = 1; i < sum; ++i)
     42     {
     43         for(int j = 0; j < n; ++j)
     44         {
     45             if(dp[i][j] == INF)
     46                 continue;
     47             if(f[i][j] != 0)
     48             {
     49                 for(int k = 0; k < n; ++k)
     50                 {
     51                     if(f[i][k] == 2 || k == j || num[j][k] == INF)
     52                         continue;     
     53                     int next = i + ab[k];
     54                     dp[next][k] = min(dp[next][k], dp[i][j] + num[j][k]);
     55                 }
     56             }
     57         }
     58     }
     59     int res = INF, s1 = 1, first = 0;     
     60     for(int i = 0; i < n; ++i)   
     61     {
     62         first += s1;  
     63         s1 *= 3;          
     64     }
     65     for(int i = first; i < sum; ++i)
     66     {
     67         int ok = 1;
     68         for(int j = 0; j < n; j++)//判断是否有城市没去过
     69         {
     70             if(f[i][j] == 0)
     71             {
     72                 ok = 0;
     73                 break;
     74             }
     75         }
     76         if(ok)
     77             for(int k = 0; k < n; ++k)
     78                 res = min(dp[i][k], res);
     79     }
     80     return res;
     81 }
     82 int main()
     83 {
     84     int a, b, c;
     85     find();
     86     while(~scanf("%d %d", &n, &m))
     87     {
     88         for(int i = 0; i < n; ++i)
     89             for(int j = 0; j < n; ++j)
     90                 num[i][j] = INF;
     91         for(int i = 0; i < m; ++i)
     92         {
     93             scanf("%d %d %d", &a, &b, &c);//还要判断重边
     94             num[a - 1][b - 1] = num[b - 1][a - 1] = min(c, num[a - 1][b - 1]);
     95         }
     96         int res = rec();                        
     97         if(res == INF)
     98             printf("-1
    ");
     99         else
    100             printf("%d
    ", res);
    101     }
    102     return 0;
    103 }
  • 相关阅读:
    「考试」省选27
    「考试」省选26
    「考试」省选25
    $dy$讲课总结
    「笔记」$Min\_25$筛
    「考试」省选24
    「总结」多项式生成函数例题(4)
    「总结」多项式生成函数相关(4)
    「考试」省选23
    「总结」后缀3
  • 原文地址:https://www.cnblogs.com/luomi/p/5675062.html
Copyright © 2020-2023  润新知