uva 10603

紫皮书的例题

照着敲了一遍,非原创

大题思路主要是三杯水,而水的总数是知道的,相当于知道第一第二杯水的体积,第三杯水的体积也就确定了。

用第一第二杯水的体积来标记数组是否遍历过

优先队列来找移动体积最少的

主要update_ans()函数进行每次判断

void update_ans(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;
    }
}

然后就是找第i杯水应该往第j杯水移动水的体积

符合条件进行入队操作

最后在ans数组寻找合适的解……!!!

#include <iostream>
#include <cstdio>
#include <cmath>
#include <cstring>
#include <algorithm>
#include <cstdlib>
#include <stack>
#include <cctype>
#include <string>
#include <malloc.h>
#include <queue>
#include <map>

using namespace std;

const int INF = 0xffffff;
const double esp = 10e-8;
const double Pi = 4 * atan(1.0);
const int Maxn = 200+5;
const int mod = 10000007;
const int dr[] = {1,0,-1,0,-1,1,-1,1};
const int dc[] = {0,1,0,-1,1,-1,-1,1};

struct Node{
    int v[3];
    int dist;
    bool operator < (const Node & rhs)const{
        return dist > rhs.dist;
    }
};

int vis[Maxn][Maxn],cap[3],ans[Maxn];

void update_ans(const Node & u){
    for(int i = 0;i < 3;i++){
        int d = u.v[i];
        if(ans[d] < 0 || u.dist < ans[d])
            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] = 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){
                    continue;
                }
                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];///计算将i倒入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]]){
                    vis[ u2.v[0] ][u2.v[1] ] = 1;
                    q.push(u2);
                }
            }
        }
    }
    while(d >= 0){
        if(ans[d] >= 0){
            printf("%d %d\n",ans[d],d);
            return;
        }
        d--;
    }
}

int main()
{
#ifndef ONLINE_JUDGE
    freopen("inpt.txt","r",stdin);
#endif
    int T,a,b,c,d;
    scanf("%d",&T);
    while(T--){
        scanf("%d%d%d%d",&a,&b,&c,&d);
        solve(a,b,c,d);
    }
    return 0;
}

时间: 2024-11-20 14:43:38

uva 10603的相关文章

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

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

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)

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

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 倒水

题意:有3个有一定容量的杯子,给定一个水的量.问是否能让一个杯子装这个给定容量的水,以及所需要倒来倒去的水的最小量.如果不能,则能倒出的比给定容量小但最接近的量,以及所需要进行倒的水的最小量. 思路:虽然是隐式图搜索的问题,其实和之前数据结构基础章节的图的题很类似,就是一个状态转换,然后深搜或宽搜.只不过这里状态的变换不是像之前那样是固定的,可以用一个多维数组来表示:这里的变换是倒水后三个杯子的容量变化.其实题目中也明确给出了状态的变化,要么某水杯倒完,要么另一水杯被装满.比如a倒向b,可以像下

uva 10603 Fill(倒水问题 BFS)

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

【路径寻找问题】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 (暴力BFS+优先队列)

题意:给定4个数,a,b,c,d,分别代表空杯子容积为a,b,一个盛满水的杯子容积为c,让你不断倒水,找一个dd,是不是存在某个时刻, 某个杯子里的水dd,和d相同,或者无限接近.让求最少的倒水量和dd(可能和d相同). 析:首先由于没有刻度,如果用数学方法计算,不好算,样例还好算一点,我们观察那个a,b,c都不大于200,挺小的,适合暴力求解. 就是把所有情况都倒一次,倒水就两种倒法,要么把一个杯子倒满,要么就是这个杯子空了,由于水量是固定的,那么确定两个杯子的水量, 那么第三个也就确定了,所

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 倒水问题

https://vjudge.net/problem/UVA-10603 题意:三个杯子,倒水问题.找出最少倒水量. 思路:路径寻找问题.不难,暴力枚举. 1 #include<iostream> 2 #include<queue> 3 #include<string> 4 #include<cstring> 5 using namespace std; 6 7 int a, b, c, d; 8 int vis[205][205]; //访问变量,因为只有