zoukankan      html  css  js  c++  java
  • Hdu 4284 状态DP 能否走完所选城市.cpp

    题意:

    已知s.b原来有多少钱 in

    以及知道 m 个去他想去的城市工作需要用多少钱以及能挣到多少钱  

    然后知道他从 a 城市到 b 城市得花多少钱..  

    问他能不能去完他想去的城市??

    给出一个 T 表示样例个数

    接下来每个样例给出一个 n m in

    表示有 n 个点 m 个想去的地方

    接下来 m 行..每行给出 a b w 代表 a 城市和 b 城市之间路费为 w

    然后有一个 h 表示他想去的城市个数

    接下来 h 行..给出 a c d 代表在a城市需要花d元 能够挣 c 元

    思路:

    状态压缩DP..

    求出城市间最短距离

    初始状态是如果从第一个城市到第 i 个城市的路费+花费 >= 0 就让这个dp[ 1<< i ][ i ]的值更新为 剩下的钱+挣的钱

    然后枚举所有的状态

    枚举所有的可能性..找出按某个顺序能挣得的钱越多的..

    然后如果最后所有方案中有一个的钱的总数 >= 0就代表他可以走遍他想去的城市..

    Tips:

     因为可能出现重边 所以要加判断语句

     dis的初始化对dis[ i ][ i ] = 0;

    Code:

    View Code
     1 #include <stdio.h>
     2 #include <cstring>
     3 using namespace std;
     4 #define clr(x) memset(x, 0, sizeof(x))
     5 const int INF = 0x1f1f1f1f;
     6 #define max(a, b) ((a) > (b)?(a):(b))
     7 
     8 int T, n, m, h, a, b, c, d, w, in;
     9 int dis[110][110], dp[1<<15][15];
    10 bool flag;
    11 
    12 struct CD
    13 {
    14     int num;
    15     int c;
    16     int d;
    17 }cd[15];
    18 
    19 void floyd()
    20 {
    21     for(int k = 1; k <= n; ++k)
    22     for(int i = 1; i <= n; ++i)
    23     for(int j = 1; j <= n; ++j) {
    24         dis[i][j] = dis[i][j]<dis[i][k]+dis[k][j]?dis[i][j]:dis[i][k]+dis[k][j];
    25     }
    26 }
    27 
    28 void solve()
    29 {
    30     int i, j, k;
    31     int tmp, st, stat;
    32 
    33     st = (1<<h)-1;
    34     memset(dp, 0xff, sizeof(dp));
    35 
    36     floyd();
    37     for(i = 0; i < h; ++i) {
    38         tmp = in-dis[1][cd[i].num]-cd[i].d;
    39         if(tmp >= 0) {
    40             dp[1<<i][i] = tmp+cd[i].c;
    41         }
    42     }
    43 
    44     for(i = 1; i <= st; ++i)
    45     for(j = 0; j < h; ++j)
    46     if(dp[i][j] >= 0) {
    47         for(k = 0; k < h; ++k)
    48         if(!(i&(1<<k))) {
    49             tmp = dp[i][j] - dis[cd[j].num][cd[k].num] - cd[k].d;
    50             if(tmp >= 0) {
    51                 stat = i+(1<<k);
    52                 dp[stat][k] = max(dp[stat][k], tmp+cd[k].c);
    53             }
    54         }
    55     }
    56 
    57     for(i = 0; i < h; ++i) {
    58         tmp = dp[st][i]-dis[cd[i].num][1];
    59         if(tmp >= 0) {
    60             flag = true;
    61             break;
    62         }
    63     }
    64 }
    65 
    66 int main()
    67 {
    68     int i, j, k;
    69     while(scanf("%d", &T) != EOF)
    70     while(T--)
    71     {
    72         memset(dis, INF, sizeof(dis));
    73         flag = false;
    74         for(i = 1; i <= n; ++i)
    75             dis[i][i] = 0;
    76 
    77         scanf("%d %d %d", &n, &m, &in);
    78         while(m--) {
    79             scanf("%d %d %d", &a, &b, &w);
    80             if(w < dis[a][b])
    81             dis[a][b] = dis[b][a] = w;
    82         }
    83         scanf("%d", &h);
    84         for(i = 0; i < h; ++i)
    85             scanf("%d %d %d", &cd[i].num, &cd[i].c, &cd[i].d);
    86 
    87         solve();
    88 
    89         if(flag) puts("YES");
    90         else puts("NO");
    91     }
    92     return 0;
    93 }

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

  • 相关阅读:
    python--模块与包
    内置函数 的总结
    迭代器 生成器 列表推导式 生成器表达式的一些总结
    函数的有用信息 带参数的装饰器 多个装饰器装饰一个函数
    函数名的应用(第一对象) 闭包 装饰器
    动态参数 名称空间 作用域 作用域链 加载顺序 函数的嵌套 global nonlocal 等的用法总结
    函数的初识 函数的返回值 参数
    文件操作 常用操作方法 文件的修改
    遍历字典的集中方法 集合的作用 以及增删查的方法
    计算机硬件的小知识
  • 原文地址:https://www.cnblogs.com/Griselda/p/2687188.html
Copyright © 2011-2022 走看看