UVa 10603 Fill (暴力BFS+优先队列)

题意:给定4个数,a,b,c,d,分别代表空杯子容积为a,b,一个盛满水的杯子容积为c,让你不断倒水,找一个dd,是不是存在某个时刻,

某个杯子里的水dd,和d相同,或者无限接近。让求最少的倒水量和dd(可能和d相同)。

析:首先由于没有刻度,如果用数学方法计算,不好算,样例还好算一点,我们观察那个a,b,c都不大于200,挺小的,适合暴力求解。

就是把所有情况都倒一次,倒水就两种倒法,要么把一个杯子倒满,要么就是这个杯子空了,由于水量是固定的,那么确定两个杯子的水量,

那么第三个也就确定了,所以我们用二维数组进行标记,我记的是前两个杯子(记任意两个都行),由于要求是倒水题最少,而不是步数最少,

首先它们没有必要的关系,并不是步数少,倒水题就少,所以我们采用优先队列,倒水量少的优先,那么倒到d时,倒水量一定是最少的,

然后就是BFS,把所有的情况都找一下,如果找到及时退出,找不到找比d小并且最近的即可。

注意标记的时候,不要标记错,我第一次标记错了,不是标记 i,j,而是固定的数。

代码如下:

#include <iostream>
#include <cstdio>
#include <cstring>
#include <queue>

using namespace std;
const int maxn = 200 + 5;
struct node{
    int val[3], d;
    bool operator < (const node &p) const {
        return d > p.d;
    }
};
int vis[maxn][maxn], ans[maxn];

void update(const node &u){//及时更新倒水量
    for(int i = 0; i < 3; ++i){
        int v = u.val[i];
        if(ans[v] < 0 || ans[v] > u.d)  ans[v] = u.d;
    }
}

void bfs(int a, int b, int c, int d){
    int cap[] = {a, b, c};//容量大小
    priority_queue<node> q;//优先队列
    memset(vis, 0, sizeof(vis));
    memset(ans, -1, sizeof(ans));
    node u;
    u.val[0] = 0;  u.val[1] = 0;//开始的状态
    u.val[2] = c;  u.d = 0;
    q.push(u);

    vis[0][0] = 1;
    while(!q.empty()){
        u = q.top();  q.pop();
        update(u);
        if(ans[d] >= 0)  break;//找到d了 及时退出

        for(int i = 0; i < 3; ++i)
            for(int j = 0; j < 3; ++j){
                if(i == j || !u.val[i] || u.val[j] == cap[j])  continue;//i 是空的,或者 j 是已经满了

                node v;    memcpy(&v, &u, sizeof(u));
                int t = min(cap[j], v.val[i]+v.val[j]) - v.val[j];//找倒水量,要么倒满,要么倒空
                v.val[i] -= t;
                v.val[j] += t;
                v.d += t;
                if(vis[v.val[0]][v.val[1]])  continue;
                vis[v.val[0]][v.val[1]] = 1;//标记的不是 vis[v.val[j]][v.val[j]]
                q.push(v);
            }

    }

    while(d >= 0){
        if(ans[d] >= 0){ printf("%d %d\n", ans[d], d);  return ;  }
        --d;//找最近的
    }
}

int main(){
//    freopen("in.txt", "r", stdin);
    int T, a, b, c, d;  cin >> T;
    while(T--){
        scanf("%d %d %d %d", &a, &b, &c, &d);
        bfs(a, b, c, d);
    }
    return 0;
}
时间: 2024-10-11 08:24:19

UVa 10603 Fill (暴力BFS+优先队列)的相关文章

uva 10603 Fill (BFS)

uva 10603 Fill There are three jugs with a volume of a, b and c liters. (a, b, and c are positive integers not greater than 200). The first and the second jug are initially empty, while the third is completely filled with water. It is allowed to pour

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

在做用户查找时 因为要把查找的结果动态加载和显示,所以,那些html元素要由Ajax动态生成.用户打开查找界面时,有系统推荐的用户,而当用户按条件查找后,查找的结果动态加载和显示.所以考虑到用js来搞. 这个for循环就是移除已有的表单.然后根据Ajax请求过来的数据,动态生成新的表单对象.一定要注意j变量从大往小循环,否则,删除div元素后会引起serchResultLenth=serchResult.children.length;长度的变化(这个问题摸索了好久,才搞定,切记) for(va

UVa 10603 Fill [暴力枚举、路径搜索]

10603 Fill There are three jugs with a volume of a, b and c liters. (a, b, and c are positive integers not greater than 200). The rst and the second jug are initially empty, while the third is completely lled with water. It is allowed to pour water f

uva 10603 Fill(倒水问题 BFS)

貌似uva崩了,现在进不去,所以这道题还判断正确与否,其实无所谓了,我这是看的网上的代码,写的基本上一样,唉,没办法,不会做,又看了网上的题解,认真写理解吧还是... 构造了一个结构体,water数组用来保存三个杯子的状态,sum用来保存当前的倒水量,visit数组用来保存状态,以 防他们重复访问,三个杯子只需要两个杯子来判断,第三个已经确定,所以开一个二维数组就可以了...然后用 reach数组来存储所有的倒水量,下标是目标水量,值是一共的倒水量... 只需要一次BFS最多有200*200种状

UVA 10603 Fill(正确代码尽管非常搓,网上很多代码都不能AC)

题目链接:option=com_onlinejudge&Itemid=8&page=show_problem&problem=1544">click here~ 此题我预计是加强过数据,在我纠结了非常久的时候我交了好几份网上的代码不是WA就是TLE.在我非常迷茫的时候我又交了一份,AC了(尽管我用随机数据找到了他代码一个不能过的数据). 给了我信心.然后我拿他的代码用随机数跟我的代码进行測试.再用FC找不同..发现了一个致命的错误.一般来说,BFS或者DFS都是须要

UVa - 10603 - Fill

BFS即可,不过需要注意要求不是步数最少,而是需要水量最少.所以拓展的时候需要取出水量最少的结点进行拓展.用优先队列即可. #include <iostream> #include <cstdio> #include <cstdlib> #include <cctype> #include <cstring> #include <string> #include <sstream> #include <vector&

【路径寻找问题】UVa 10603 - Fill

如家大神书上的例题.第一次接触也是按代码敲得.敲的过程感觉很直观.但自己写估计会写的乱七八糟.以后不能砍得难就不愿意做这种题.否则只能做一些水题了.(PS:48) 紫书 1 #include<iostream> 2 #include<cstdio> 3 #include<cstdlib> 4 #include<cstring> 5 #include<queue> 6 using namespace std; 7 const int maxn =

UVA - 10603 Fill(隐式图搜索)

题目大意:经典的倒水问题.给你三个瓶子,体积为a,b,c. 刚开始a,b是空的,c是满的,现在要求你到出体积为d的水.倒水的规则为,要么倒水方为空,要么接水方满 问倒到容量为d时,倒水的最小体积是多少,如果不能倒出体积为d的水,找出d' < d,最接近d的d'和最小的体积 解题思路:刚才时以为直接bfs,用vis标记一下就结束了,结果WA了.为什么会WA,因为我这样求的是倒水次数最少的,而不是倒水体积最小的,WA是肯定的了 接着将vis数组改成int型的,纪录达到这个状态时倒水的体积,结果可想而

UVA 10603 Fill倒水问题

There are three jugs with a volume of a, b and c liters. (a, b, and c are positive integers not greater than 200). The ?rst and the second jug are initially empty, while the third is completely ?lled with water. It is allowed to pour water from one j