UVA - 10603 Fill(BFS求最小值问题)
Posted sykline
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了UVA - 10603 Fill(BFS求最小值问题)相关的知识,希望对你有一定的参考价值。
题目:
给出三个杯子(没有刻度线)的容量,起初之后第三个杯子是满的,其他的两个杯子是空的,容量分别是a、b、c。问最少需要倒多少升水才能让
某一个杯子中的水有d升?如果不能恰好做到d升,就让某一个杯子里的水是D升,其中D<d并且尽量接近d。(1≤a,b,c,d≤200)。要求输出最少的
倒水量和目标水量d或D。
思路:
菜是原罪,需要赎罪啊!!
1.一看到这种求最小值的问题很应该想到是用BFS了。
2.BFS需要标记状态呀,那201*201*201=8120601这内存有些吃不消啊,那前两个杯子的水固定了,总的水量又是不变的,那只用前两个杯子的
水量就可以标记所有可能的状态了。这样就把状态缩小到201*201了。
3.Node结构体中保存的是一个状态,“状态”这个词很玄乎啊,有到当前状态已经倒过的水量dist和三个杯子中还有的水量v[0]、v[1]、v[2]。
4.紫书的代码写的优美啊!!值的好好的学习!!
代码:
#include <bits/stdc++.h> #define inf 0x3f3f3f3f #define MAX 1000000009 #define FRE() freopen("in.txt","r",stdin) #define FRO() freopen("out.txt","w",stdout) using namespace std; typedef long long ll; const int maxn = 205; struct Node{ int v[3],dist;//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] = start.v[1] = 0; start.v[2] = c; q.push(start); vis[0][0] = 1;//标记a、b杯子为空的状态 while(!q.empty()){ Node u = q.top();q.pop(); update_ans(u); if(ans[d]>=0) break;//如果已经找到的答案就break for(int i=0; i<3; i++){//i表示的是倒出水的杯子 for(int j=0; j<3; j++){//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];//重点了!! /* 要倒一定是全部倒出来,所以j杯子被倒水之后有两种状态 1.倒之后满了 2.倒之后没有满 从这两种状态中取一个最小的水量记录下来 */ 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 ",ans[d],d); return; } d--; } } int main(){ 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; }
以上是关于UVA - 10603 Fill(BFS求最小值问题)的主要内容,如果未能解决你的问题,请参考以下文章