Nyoj 21 三个水杯(bfs)
Posted
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了Nyoj 21 三个水杯(bfs)相关的知识,希望对你有一定的参考价值。
三个水杯
时间限制:1000 ms | 内存限制:65535 KB
难度:4
描述
给出三个水杯,大小不一,并且只有最大的水杯的水是装满的,其余两个为空杯子。三个水杯之间相互倒水,并且水杯没有标识,只能根据给出的水杯体积来计算。现在要求你写出一个程序,使其输出使初始状态到达目标状态的最少次数。
输入
第一行一个整数N(0<N<50)表示N组测试数据
接下来每组测试数据有两行,第一行给出三个整数V1 V2 V3 (V1>V2>V3 V1<100 V3>0)表示三个水杯的体积。
第二行给出三个整数E1 E2 E3 (体积小于等于相应水杯体积)表示我们需要的最终状态
输出
每行输出相应测试数据最少的倒水次数。如果达不到目标状态输出-1
样例输入
2
6 3 1
4 1 1
9 3 2
7 1 1
样例输出
3
-1
-
#include <stdio.h>
-
#include <string.h>
-
#define MAX 1000
-
typedef struct STATE{
-
int x;
-
int y;
-
int step;
-
}state;//状态表示第一个杯子中有x升水,第二个杯子中有升水,step表示到当前状态所需步数
-
state que[MAX],p,q;//que为队列
-
int f,r;
-
int N,A,B,C,x,y,z,d,newx,newy;
-
int vis[MAX][MAX];//标记数组记录某状态是否收录过
-
void push(){
-
que[r].x=newx;
-
que[r].y=newy;
-
que[r++].step=q.step+1;
-
vis[newx][newy]=1;
-
}
-
int bfs(){
-
que[r].x=A;
-
que[r].y=0;
-
que[r++].step=0;
-
vis[A][0]=1;
-
while(f<r){
-
q.x=que[f].x;
-
q.y=que[f].y;
-
q.step=que[f].step;
-
if(q.x == x&&q.y == y) return q.step;//满足条件时输出步数
-
f++;
-
if(q.x>0){//若A杯中有水,判断将A中水倒入B,C杯的状态是否出现过并收到队列中
-
if(B-q.y>=q.x){
-
newx=0;
-
newy=q.y+q.x;
-
if(!vis[newx][newy])push();
-
}
-
else {
-
newx=q.x-B+q.y;
-
newy=B;
-
if(!vis[newx][newy])push();
-
}
-
if(C-(A-q.y)>=0){
-
newx=0;
-
newy=q.y;
-
if(!vis[newx][newy])push();
-
}
-
else {
-
newx=(A-q.y)-C;
-
newy=q.y;
-
if(!vis[newx][newy])
-
push();
-
}
-
}
-
if(q.y>0){//B中水杯倒入A一定可以倒完,故不用判断,倒入C中则需要
-
newy=0;
-
newx=q.x+q.y;
-
if(!vis[newx][newy])
-
push();
-
if(C-(A-q.x)>=0){
-
newx=q.x;
-
newy=0;
-
if(!vis[newx][newy]) push();
-
}
-
else {
-
newx=q.x;
-
newy=(A-q.x)-C;
-
if(!vis[newx][newy])push();
-
}
-
}
-
if(A-q.x-q.y>0){//倒入A杯中情况同样不需要判断
-
newx=A-q.y;
-
newy=q.y;
-
if(!vis[newx][newy])push();
-
if(B>=A-q.x){
-
newx=q.x;
-
newy=A-q.x;
-
if(!vis[newx][newy])push();
-
}
-
else {
-
newx=q.x;
-
newy=B;
-
if(!vis[newx][newy])push();
-
}
-
}
-
}
-
return -1;
-
}
-
int main(){
-
scanf("%d",&N);
-
while(N--){
-
scanf("%d%d%d",&A,&B,&C);
-
scanf("%d%d%d",&x,&y,&z);
-
printf("%d\n",bfs());
-
memset(vis,0,sizeof(vis));
-
f=r=0;
-
}
-
return 0;
-
}
这道题目其实就是对解答图的bfs,从某一状态转移到另一状态,状态的表示和那道无脑博士是一样的,当是两道题所需解不一样因此所用搜索方式也不同,那道题需要多个状态解,而这道需要某个特殊状态解,由此可以看出两种方式适用的问题。做这题要解决的问题只有两个,状态的表示,bfs的使用,无脑那道题把这个问题解决了,而第二个问题对于从早上1点起床开始,到下午6点一直在做用bfs解决的迷宫问题(虽然最后一道也没做出来。。)已经不算问题 了,于是这题自然而然地AC出来了,而且这题还给了一个条件V1>V2>V3。这样的话需要的判断就更少了(这里误以为C倒入B一定可以倒满,WA了一次),一开始MAX定太大,结果MLE了,这还是人生第一次呢。。,话说,这道题用了72ms,而看了下排行发现,一大堆丧性病狂 的0ms。。。。,好像用了STL里的黑魔法,那个就暂时学不来了,这时间我已经很满意了,昨天家里停电,早上把电脑撸没电了,于是下午只能安静地看书,终于把C++prime的第二章给撸完了,看完很high,准备把引用,指针,const,还有那些C++11新特性,也就是第二章内容做个小结,9点多开始写,撸到2点多,终于快写完了,结果临时保存区爆了,突然出现奇怪的bug,2000多字的纯手打内容都没了(自行脑补暴走表情),差点哭出来,但我睡了一觉起来后,心情平复了便接受了这个事实,开始前天的打算练习bfs,结果尼玛,在计蒜客做了两道迷宫类题目,愣是没做出来一道,老是超时,心情老不爽,于是转到nyoj想找其它题目做,就随便打开一道,没想到刚好是bfs,就动手做了起来,一开始没想能做出来的,因为是难度4啊,但是做了才发现,原来不难,AC后心情总算回复了,这道题是我第一道不看题解做出来的难度4题目,也是第一道成功AC的bfs类题目,还是第一道MLE的题目。。。,果然练习算法还是要找经典题目做比较好啊,o(* ̄▽ ̄*)ブ。
以上是关于Nyoj 21 三个水杯(bfs)的主要内容,如果未能解决你的问题,请参考以下文章