zoukankan      html  css  js  c++  java
  • Fill-倒水问题(Uva-10603-隐式图路径寻找问题)

    原题:https://uva.onlinejudge.org/external/106/10603.pdf


    有三个没有刻度的杯子,它们的容量分别是a, b, c, 最初只有c中的杯子装满水,其他的被子都是空的。问如果通过倒水得到d升水, 若可以得到,还要求最少的倒水总量(每倒一次水,都加入到总量里)。若不能得到d升水,求比d小的距离d最近的d'升水, 及最少倒水总量。

     


    分析:

    因为是求最少倒水总量,本能地想到用bfs搜索。最开始读错题了...看成求倒水的最少次数,这个很简单.....我们可以把求解的过程看成是空间状态的搜索,每一个状态都有一组a, b, c, pour_amount (分别对应三个杯子里的水量和到达当前状态需要的倒水总量)。如果把每个状态想象成一个结点, 整个搜索的过程就是图的遍历过程。


    难点:

    这道题的每一个状态有四个变量,所以要考虑所有四种变量的所有变化情况。方法是每次枚举当前a,b,c的下一个可达结点。这里有一个可以回溯剪枝的要点,就是结点判重,如果下一个结点的a,b,c曾经遍历过且它的pour_amount小于当前的pour_amount,回溯.结点判重的时候还有一个难点就是自己实现一个哈希表.对于一个状态a,b,c,对应一个到达这个状态的最小pour_amount

    如果用stl自带的map,速度非常慢,比如1000组数据需要耗时4s左右

    然而如果用自己实现的hash_map,1000组数据只要0.003s

     1 #include <cstdio>
     2 #include <cstdlib>
     3 #include <cstring>
     4 #include <algorithm>
     5 #include <queue>
     6 using namespace std;
     7 
     8 const int MAXHASHSIZE = 500;
     9 int d, _head[MAXHASHSIZE], _next[MAXHASHSIZE];
    10 int vol[3], _d, ans, idx, st[MAXHASHSIZE], pour_set[MAXHASHSIZE];
    11 
    12 struct Node {
    13     int v[3], pour; 
    14     Node(int a = 0, int b = 0, int c = 0, int p = 0) {
    15         v[0] = a; v[1] = b; v[2] = c; pour = p;
    16     }
    17     bool operator == (const Node &rhs) const {
    18         for (int i = 0; i < 3; i++) if (rhs.v[i] != v[i]) return false;
    19         if (rhs.pour != pour) return false;
    20         return true;
    21     }
    22 };
    23 
    24 void init() {
    25     _d = -1;
    26     ans = 2147483647;
    27     idx = 1;
    28     memset(_head, 0, sizeof(_head));   
    29 }
    30 
    31 bool try_to_insert(Node &cur) {
    32     int status = cur.v[0] * 1000000 + cur.v[1] * 1000 + cur.v[2];
    33     int h = status % MAXHASHSIZE;
    34     int u = _head[h];
    35     while (u) {
    36         if (st[u] == status) {
    37             if (cur.pour < pour_set[u]) {
    38                 pour_set[u] = cur.pour;
    39                 return 1;
    40             }
    41             return 0;
    42         }
    43         u = _next[u];
    44     }
    45     st[idx] = status;
    46     pour_set[idx] = cur.pour;
    47     _next[idx] = _head[h];
    48     _head[h] = idx++;
    49     return 1;
    50 }
    51 
    52 void bfs(Node start) {
    53     pour_set[1] = start.pour;
    54     try_to_insert(start);
    55     queue<Node> q; 
    56     q.push(start);
    57     while (!q.empty()) {
    58         Node cur = q.front(); q.pop();
    59         for (int i = 0; i < 3; i++) {
    60             if (cur.v[i] == _d)
    61                 ans = min(ans, cur.pour);
    62             else if (cur.v[i] > _d && cur.v[i] <= d) {
    63                 ans = cur.pour; 
    64                 _d = cur.v[i];
    65             }
    66             if (cur.v[i] != 0)
    67                 for (int j = 0; j < 3; j++) if (i != j) {
    68                     int pour = min(cur.v[i], vol[j] - cur.v[j]);
    69                     cur.v[i] -= pour;
    70                     cur.v[j] += pour;
    71                     Node nextn = Node(cur.v[0], cur.v[1], cur.v[2], cur.pour + pour);
    72                     cur.v[i] += pour;
    73                     cur.v[j] -= pour;
    74                     if (try_to_insert(nextn)) q.push(nextn);
    75                 }
    76         }
    77     }
    78 }
    79 
    80 int main() {
    81     int T;
    82     scanf("%d", &T);
    83     while (T--) {
    84         init();
    85         scanf("%d%d%d%d", &vol[0], &vol[1], &vol[2], &d);
    86         bfs(Node(0, 0, vol[2], 0));
    87         printf("%d %d
    ", ans, _d);
    88     }
    89     return 0;
    90 }

     

  • 相关阅读:
    大型架构.net平台篇(中间层均衡负载WCF)
    大型高性能ASP.NET系统架构设计
    百万级访问量网站的技术准备工作
    容器管理的分布式事务
    SQL Server 2005实现负载均衡
    nginx负载均衡 tomcat集群 memcache共享session
    JTA实现跨数据库操作
    [AX]AX2012 Table的AOSAuthorization 属性
    [AX]AX2012 Form上的ReferenceGroup control
    [AX]AX2012 Form开发概览
  • 原文地址:https://www.cnblogs.com/Bowen-/p/4947158.html
Copyright © 2011-2022 走看看