zoukankan      html  css  js  c++  java
  • 状态压缩DP 之 poj 2686

    第一次做状态压缩DP,之前敲了一个 “旅行商问题” ,对状态压缩DP,有了一定了解,对此题的理解和解决有很大的帮助。

    //  [4/29/2014 Sjm]
    /*
     
    状态压缩: 针对集合的DP。
     
    题意: 
    旅行家从 a 出发,此时有 S 张车票,为到达 b,求花费最短的时间。
     
    分析: 
    假设"在 v 点时,旅行商有 S 张票",
    每到达与 a 相邻的国家,需要用掉一张车票i,所到达的国家设为 u,
    此时"在 u 点时, 旅行商有 S{i} 张票",
    再到达与 u 相邻的国家,以此类推.....直至到达 b 国家。
     
    总结:
    在分析中可以看到状态的转换:
         "在 v 点时,旅行商有 S 张票"  ----->  在 u 点时, 旅行商有 S{i} 张票
    而转移的开销是: (两点间距离)/ (马匹的数目)。
    (可以将上述过程看成建图过程,状态即顶点,转移即边,转移的开销即边的权值)
    由于 S(即车票)是集合,故而考虑状态压缩DP解决。
     
    综上:
    状态:
    dp[S][v] := 当此时所到达点为 v并且 所剩票数为 S 时,所需要的最小花费
    决策:
    dp[S & ~(1<<i)][u] = min(dp[S & ~(1<<i)][u], dp[S][v] + (double)d[v][u] / myT[i])
     
    */
     1 #include <iostream>
     2 #include <cstdio>
     3 #include <cstdlib>
     4 #include <algorithm>
     5 using namespace std;
     6 const int MAX_N = 8, MAX_M = 30, INF = 0x3f3f3f3f;
     7 
     8 int n, m, p, a, b;
     9 int myT[MAX_N];  // 马匹数
    10 int d[MAX_M][MAX_M];  // 各国家间道路的距离(-1表示没有道路)
    11 double dp[1 << MAX_N][MAX_M];
    12 
    13 void Solve()
    14 {
    15     double ans = 1.0 * INF;
    16     for (int i = 0; i < 1 << n; i++)
    17         fill(dp[i], dp[i] + m, INF);
    18     dp[(1 << n) - 1][a - 1] = 0;
    19     for (int S = (1 << n) - 1; S >= 0; S--) {
    20         ans = min(ans, dp[S][b - 1]);
    21         for (int v = 0; v < m; v++) {
    22             for (int i = 0; i < n; i++) {
    23                 if (S >> i & 1) {
    24                     for (int u = 0; u < m; u++) {
    25                         if (d[v][u] >= 0) {
    26                             // 使用车票 i, 从 v 移动到 u。
    27                             dp[S & ~(1 << i)][u] = min(dp[S & ~(1 << i)][u], dp[S][v] + (double)d[v][u] / myT[i]);
    28                         }
    29                     }
    30                 }
    31             }
    32         }
    33     }
    34     if (INF == ans) printf("Impossible
    ");
    35     else printf("%.3f
    ", ans);
    36 }
    37 
    38 int main()
    39 {
    40     //freopen("input.txt", "r", stdin);
    41     //freopen("output.txt", "w", stdout);
    42     while (scanf("%d %d %d %d %d", &n, &m, &p, &a, &b) && (n || m || p || a || b)) {
    43         for (int i = 0; i < n; i++)
    44             scanf("%d", &myT[i]);
    45         memset(d, -1, sizeof(d));
    46         for (int i = 0; i < p; i++) {
    47             int x, y, z;
    48             scanf("%d %d %d", &x, &y, &z);
    49             d[x-1][y-1] = d[y-1][x-1] = z;
    50         }
    51         Solve();
    52     }
    53     return 0;
    54 }



  • 相关阅读:
    使用postman模拟上传文件到springMVC的坑:the request was rejected because no multipart boundary was found
    win10 安装多个版本的jdk,如何切换
    String类的substring方法
    tomcat7.0配置CORS(跨域资源共享)
    win7下安装centos6.5后,开机无法进入选择双系统启动界面,只能启动centos的解决办法
    java位运算
    JDK源码--ArrayList浅析
    使用Jasperreporter生成入库出库单打印等报表操作
    centos6.5下安装zip格式的tomcat7和tomcat8,并同时运行
    Centos7配置文件共享服务器SAMBA三步曲(转)
  • 原文地址:https://www.cnblogs.com/shijianming/p/4140854.html
Copyright © 2011-2022 走看看