倒水问题(Fill,UVa 10603)

原创 2015年11月19日 17:04:48

原题链接

分析:由于有三个杯子,每个杯子中的水量可能不同,假设水量分别为a,b,c,则水量a,b,c就对应一种存在状态,则题目可以抽象为从初始状态0,0,c开始寻找一种最优的路径(倒水量最少)使之达到目标状态(其中一个杯子水量为d(d'))。因此具体做法就是用BFS从初始状态(0,0,c)开始枚举每种状态,直至达到目标状态即可。

PS:此题中还存在一些小细节,由于有三个杯子,因此状态共有(a+1)*(b+1)*(c+1)种可能,但是初始水量是一定的,所以只需要判断前两个杯子的状态就可以确定整个状态;

还有就是优先队列的使用,重载<运算符使之先判断水量最少的状态可以减少枚举次数。

<strong><span style="font-size:18px;">#include<cstdio>
#include<iostream>
#include<algorithm>
#include<cstring>
#include<vector>
#include<string>
#include<map>
#include<cmath>
#include<sstream>
#include<queue>
#include<cctype>
using namespace std;
typedef long long ll;
#define MAX 205
// 定义状态变量
struct Node {
        int v[3],dist;
        // 重载<运算符使队首为队列中dist最小值元素
        bool operator < (const Node& rhs) const {
                return dist > rhs.dist;
        }
};
int vis[MAX][MAX],cap[3],ans[MAX];
// 更新水量为d时的最优解
void update_ans(const Node& u) {
        for(int i=0;i<3;i++) {
                int d = u.v[i];
                if(ans[d] < 0 || ans[d] > u.dist) ans[d] = u.dist;
        }
}
void solve(int a,int b,int c,int d) {
        cap[0] = a;cap[1] = b;cap[2] = c;
        memset(vis,0,sizeof(vis));
        memset(ans,-1,sizeof(ans));
        priority_queue<Node> q;
        Node start;
        // 初始化初始状态
        start.dist = 0;
        start.v[0] = start.v[1] = 0;
        start.v[2] = c;
        q.push(start);
        vis[0][0] = 1;
        while(!q.empty()) {
                Node u = q.top();q.pop();
                update_ans(u);
                if(ans[d] >= 0) break;
                // 枚举状态
                for(int i=0;i<3;i++)
                for(int j=0;j<3;j++)
                if(i != j) {
                        if(u.v[i] == 0 || u.v[j] == cap[j]) continue;
                        int amount = min(cap[j],u.v[i] + u.v[j]) - u.v[j];
                        Node u2;
                        memcpy(&u2,&u,sizeof(u));
                        u2.dist = u.dist + amount;
                        u2.v[i] -= amount;
                        u2.v[j] += amount;
                        // 判断此状态是否已访问
                        if(!vis[u2.v[0]][u2.v[1]]) {
                                q.push(u2);
                                vis[u2.v[0]][u2.v[1]] = 1;
                        }
                }
        }
        while(d >= 0) {
                if(ans[d] >= 0) {
                        printf("%d %d\n",ans[d],d);
                        return;
                }
                d--;
        }
}
int main() {
        int T;
        while(~scanf("%d",&T) && T) {
                while(T--) {
                        int a,b,c,d;
                        scanf("%d%d%d%d",&a,&b,&c,&d);
                        solve(a,b,c,d);
                }
        }
        return 0;
}
</span></strong>


uva 10603 Fill(倒水问题 BFS)

貌似uva崩了,现在进不去,所以这道题还判断正确与否,其实无所谓了,我这是看的网上的代码,写的基本上一样,唉,没办法,不会做,又看了网上的题解,认真写理解吧还是。。。 构造了一个结构体,water数组...
  • sinat_22659021
  • sinat_22659021
  • 2015年07月30日 12:33
  • 1100

UVa 10603 - Fill,经典倒水问题+隐式图搜索+dfs

题目链接: http://uva.onlinejudge.org/index.php?option=com_onlinejudge&Itemid=8&category=110&page=show_p...
  • shuangde800
  • shuangde800
  • 2012年07月24日 02:08
  • 4271

UVA 10603 Fill(正确代码虽然很搓,网上许多代码都不能AC)

题目链接:click here~ 此题我估计是加强过数据,在我纠结了很久的时候我交了好几份网上的代码不是WA就是TLE。在我很迷茫的时候我又交了一份,AC了(虽然我用随机数据找到了他代码一个不能过的...
  • u012962816
  • u012962816
  • 2014年05月07日 17:45
  • 1818

UVA 10603 Fill倒水问题

There are three jugs with a volume of a, b and c liters. (a, b, and c are positive integers not grea...
  • wust_ZJX
  • wust_ZJX
  • 2015年08月06日 09:16
  • 452

UVA 10603 Fill(倒水问题)

Fill There are three jugs with a volume of a, b and c liters. (a, b, and c are positive integ...
  • disparity_CJK
  • disparity_CJK
  • 2016年10月29日 18:31
  • 161

例题7-8 UVA 10603 Fill 倒水问题

完全仿照紫书上来写的! 书中大体思路是: 用ans[]来记录答案,不断取最小值来更新! 用vis[][]来表示是否访问过,之所以是二维数组,是因为总水量是固定的,两个杯子确定,第三个杯子自然也就确定,...
  • aozil_yang
  • aozil_yang
  • 2016年03月04日 07:57
  • 420

UVA 10603 Fill(状态空间搜索,倒水问题)

【题目链接】uva-10603 【题意】设3个杯子的容量分别为a, b, c,最初只有第3个杯子装 满了c升水,其他两个杯子为空。最少需要倒多少升水才能让某一个杯子中的水有d升呢?如果无法做到恰好d升...
  • qq_34845082
  • qq_34845082
  • 2017年08月04日 14:36
  • 156

Fill (Uva 10603 bfs 倒水问题)

题意:三个杯子容量分别为a,b,c,现在c是满的,a和b是空的,两个杯子 i 向 j 倒水,要么 i 倒完了 j 还没满,要么 j 满了 i 还有剩余,问达到某个杯子水量为d时总共倒得最小水量是多少?...
  • u014422052
  • u014422052
  • 2015年08月13日 09:24
  • 744

例题7-8 倒水问题(Fill, UVa 10603)

1. 粗略估计状态数不超过40401,枚举所有状态,来搜索最接近的d。 2. 本题的目标是倒水量最少,定义从状态s到状态v的边权为vol,类似dijkstra做法。#include #includ...
  • chcnsn
  • chcnsn
  • 2017年10月15日 09:52
  • 63

uva 10603 倒水问题

刘汝佳那本书上的代码有些问题,判断当前三个瓶子的水量状态是否被访问过后,还要判断当前状态的使用水量是否比之前的要少。如果少那么需要更新到达该状态的水量。 不知道是最近重新上传了测试数据还是其他原因,...
  • u014097230
  • u014097230
  • 2017年06月30日 23:33
  • 115
内容举报
返回顶部
收藏助手
不良信息举报
您举报文章:倒水问题(Fill,UVa 10603)
举报原因:
原因补充:

(最多只允许输入30个字)