原题: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\n", ans, _d);
88     }
89     return 0;
90 }


转载于:https://www.cnblogs.com/Bowen-/p/4947158.html

Fill-倒水问题(Uva-10603-隐式图路径寻找问题)相关推荐

  1. 题目2:隐式图的搜索问题(A*算法解决八数码)

    数据结构课程实践系列 题目1:学生成绩档案管理系统(实验准备) 题目2:隐式图的搜索问题(A*算法解决八数码) 题目3:文本文件单词的检索与计数(实验准备) 文章目录 数据结构课程实践系列 题目1:学 ...

  2. 《数据结构课程实践》_02_隐式图的搜索问题_准备工作

    02_隐式图的搜索问题_准备工作 一.实验题目与要求 二.编程语言以及开发环境 三.实验思路 A*算法 四.预习小结 一.实验题目与要求 实验要求: 对九宫重排问题,建立图的启发式搜索求解方法: 用A ...

  3. 《数据结构课程实践》_02_隐式图的搜索问题_实现

    02_隐式图的搜索问题_实现 一.实验题目 二.编程语言以及开发环境 三.源代码 1.main类 2.节点类 3.算法类 四.运行结果 五.实验小结 一.实验题目 实验要求: 对九宫重排问题,建立图的 ...

  4. 隐式图的搜索问题(九宫重排)——实验准备

    隐式图的搜索问题(九宫重排)--实验准备 隐式图的搜索问题(九宫重排) 实验任务 实验要求 A*算法 隐式图的搜索问题(九宫重排) 实验任务 对九宫重排问题,建立图的启发式搜索求解方法. 用A*算法求 ...

  5. 隐式图的搜索问题(九宫重排)——项目实现

    隐式图的搜索问题(九宫重排)--项目实现 隐式图的搜索问题(九宫重排)--项目实现 源代码 运行结果 隐式图的搜索问题(九宫重排)--项目实现 源代码 package SearchPath;publi ...

  6. 2.隐式图的搜索问题

    题目2:隐式图的搜索问题 实验内容 对九宫重排问题,建立图的启发式搜索求解方法: 用A*算法求解九宫重排问题. 实验要求 3х3九宫棋盘,放置数码为1~8的8个棋子,棋盘中留有一个空格,空格周围的棋子 ...

  7. 题目2:隐式图的搜索问题(实验准备)

    题目2:隐式图的搜索问题(实验准备) 实验内容 实验要求 编程语言的选择 项目思路 项目解析 算法选择 A*算法 实验内容 对九宫重排问题,建立图的启发式搜索求解方法: 用A*算法求解九宫重排问题. ...

  8. 实践项目—隐式图的搜索(预习报告)

    文章目录 实验内容 实验要求 编程语言及开发环境 实验思路 一.A*算法 二.A*算法解决九宫格问题 实验内容 1.对九宫重排问题,建立图的启发式搜索求解方法. 2.用A*算法求救九宫重排问题. 实验 ...

  9. 题目2:隐式图的搜索问题(A*算法解决八数码)代码实现

    从起点 开始,把它加入到一个由方格组成的open list(开放列表) 中,这个open list像是一个购物清单.Open list里的格子是可能会是沿途经过的,也有可能不经过.因此可以将其看成一个 ...

最新文章

  1. 用C#2.0实现网络蜘蛛(WebSpider)
  2. C语言之计算大数阶乘,如计算100!和1000!等~~~
  3. CodeForces - 888G Xor-MST(贪心+字典树+最小生成树)
  4. qt绘制一圈圆_Qt绘制圆形,矩形等图形   绘制同心圆
  5. 【转】4.3SharePoint服务器端对象模型 之 使用CAML进行数据查询(Part 3)
  6. 用C#编写一个进程外的COM组件示例代码讲解
  7. 瑞星2009网络版-服务器端安装和配置
  8. 如何取得GridView被隐藏列的值
  9. virtualenv -- python虚拟沙盒
  10. ENVI的seamless mosaic工具详解
  11. 在WINDOWS XP环境下部署基于网络的开源入侵监测平台——snort
  12. 信息熵,交叉熵,KL散度,JS散度之间的关系
  13. 三端稳压管原理、作用、解决发热的问题
  14. 赛尔号什么时候支持html5,赛尔号5月25日更新攻略汇总 赛伯斯特完全体降临
  15. Postgres-XL集群的搭建和测试详解
  16. 万洲金业:投资现货黄金的收益与风险如何平衡?
  17. Win7如何显示/隐藏Administrator账号
  18. MFC中进度条的学习
  19. 精读《设计模式 - Adapter 适配器模式》
  20. 美通企业日报 | 应届生平均起薪7566元京沪最高;00后月均零花钱约470元

热门文章

  1. OracleOraDb11g_home1TNSListener 服务启动后停止 某些服务在未由其他服务或程序使用时将自动停止
  2. Linux使用LVM逻辑卷 给分区扩容 不重启 热扩容
  3. python环境配置(一)——Linux下将python2.6升级到2.7 安装pip 以及升级中遇到问题的解决方法
  4. 不吹不黑 | 聊聊为什么要用99%精度的数据回测
  5. 海龟交易法则06_掌握优势
  6. 回测引擎代码分析流程图
  7. pycharm调试debug入门
  8. 配置csrf_django 入门第一课 配置文件
  9. “工业4.0”下的可视化工厂建设方案 1
  10. 实例:供应商管理报表需求调研报告