uva10603
2016-05-15 22:34
337 查看
题目描述:http://acm.hust.edu.cn/vjudge/problem/viewProblem.action?id=19527
/* solution: 还是把状态看成结点,然后以隐式图的方法去扩展结点,其过程跟dijkstra算法有点类似。 note: 隐式图 date: 2016/5/4 */ #include <iostream> #include <cstdio> #include <queue> #include <cstring> using namespace std; const int maxn = 200 + 5; int vis[maxn][maxn], ans[maxn], cap[3], d; //ans[i]代表在这个杯子里有i量的水,转移了多少量的水 struct Node { int v[3], dist; bool operator < (const Node& rhs) const { return dist > rhs.dist; } }; int main() { //freopen("input.txt", "r", stdin); int kase; scanf("%d", &kase); while(kase--) { scanf("%d%d%d%d", &cap[0], &cap[1], &cap[2], &d); memset(vis, 0 ,sizeof(vis)); memset(ans, -1, sizeof(ans)); Node start; start.dist = 0; start.v[0] = start.v[1] = 0; start.v[2] = cap[2]; //初始化开始结点 priority_queue<Node> pq; pq.push(start); vis[0][0] = 1; while(!pq.empty()) { Node x = pq.top(); pq.pop(); for(int i = 0; i < 3; i++) { int d = x.v[i]; if(ans[d] < 0 || x.dist < ans[d]) ans[d] = x.dist; //更新ans数组中的值 } if(ans[d] >= 0) break; //扩展节点,从3个杯子里选出两个,把其中一个倒进另外一个 for(int i = 0; i < 3; i++) //把i号杯子里的水倒进j号杯子里 for(int j = 0; j < 3; j++) if(i != j) { if(x.v[i] == 0 || x.v[j] == cap[j]) continue; int amount = min(cap[j], x.v[i] + x.v[j]) - x.v[j]; //求出最小应该倒多少水 //扩展结点 Node x2; memcpy(&x2, &x, sizeof(x)); x2.v[i] -= amount; x2.v[j] += amount; x2.dist = x.dist + amount; if(!vis[x2.v[0]][x2.v[1]]) { vis[x2.v[0]][x2.v[1]] = 1; pq.push(x2); } } } while(d >= 0) { if(ans[d] >= 0) { printf("%d %d\n", ans[d], d); break; } d--; } } return 0; }
相关文章推荐
- HDU 3966 Aragorn's Story 树链剖分
- spark性能优化:shuffle调优
- ViewPager中自带的pagerTabStrip切换(选项卡)
- UMDH查内存泄漏
- 在windows下,git webhook使用php拉取代码的学习总结
- Linux指令学习
- linux及shell相关学习
- 2016"百(sha)度(bi)之星"-资格赛(Astar Round 1)题解
- javascript的bom对象中的window对象
- 关于Promise的一个案例
- 浅谈 C/S 和 B/S 架构
- DQL、DML、DDL、DCL的概念与区别
- 类模版的分离编译
- UCOSIII初次学习知识点
- TaskScheduler内幕天机:Spark shell案例,TaskScheduler和SchedulerBackend、FIFO与FAIR、Task运行时本地性算法详解
- cf 66A Petya and Java
- IOS之Foundation框架
- php数据库mysql
- CentOS7下的grub2添加win7引导
- 排序常用的三种算法