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

  1. #include <stdio.h>
  2. #include <string.h>
  3. #define MAX 1000
  4. typedef struct STATE{
  5.     int x;
  6.     int y;
  7.     int step;
  8. }state;//状态表示第一个杯子中有x升水,第二个杯子中有升水,step表示到当前状态所需步数
  9. state que[MAX],p,q;//que为队列
  10. int f,r;
  11. int N,A,B,C,x,y,z,d,newx,newy;
  12. int vis[MAX][MAX];//标记数组记录某状态是否收录过
  13. void push(){
  14.     que[r].x=newx;
  15.     que[r].y=newy;
  16.     que[r++].step=q.step+1;
  17.     vis[newx][newy]=1;
  18. }
  19. int bfs(){
  20.     que[r].x=A;
  21.     que[r].y=0;
  22.     que[r++].step=0;
  23.     vis[A][0]=1;
  24.     while(f<r){
  25.        q.x=que[f].x;
  26.        q.y=que[f].y;
  27.        q.step=que[f].step;
  28.        if(q.x == x&&q.y == y) return q.step;//满足条件时输出步数
  29.        f++;
  30.        if(q.x>0){//若A杯中有水,判断将A中水倒入B,C杯的状态是否出现过并收到队列中
  31.             if(B-q.y>=q.x){
  32.                 newx=0;
  33.                 newy=q.y+q.x;
  34.                 if(!vis[newx][newy])push();
  35.             }
  36.             else {
  37.                 newx=q.x-B+q.y;
  38.                 newy=B;
  39.                 if(!vis[newx][newy])push();
  40.             }
  41.             if(C-(A-q.y)>=0){
  42.                 newx=0;
  43.                 newy=q.y;
  44.                 if(!vis[newx][newy])push();
  45.             }
  46.             else {
  47.                 newx=(A-q.y)-C;
  48.                 newy=q.y;
  49.                 if(!vis[newx][newy])
  50.                 push();
  51.             }
  52.        }
  53.        if(q.y>0){//B中水杯倒入A一定可以倒完,故不用判断,倒入C中则需要
  54.             newy=0;
  55.             newx=q.x+q.y;
  56.             if(!vis[newx][newy])
  57.             push();
  58.              if(C-(A-q.x)>=0){
  59.                 newx=q.x;
  60.                 newy=0;
  61.                 if(!vis[newx][newy]) push();
  62.             }
  63.             else {
  64.                 newx=q.x;
  65.                 newy=(A-q.x)-C;
  66.                 if(!vis[newx][newy])push();
  67.             }
  68.        }
  69.        if(A-q.x-q.y>0){//倒入A杯中情况同样不需要判断
  70.             newx=A-q.y;
  71.             newy=q.y;
  72.             if(!vis[newx][newy])push();
  73.             if(B>=A-q.x){
  74.                 newx=q.x;
  75.                 newy=A-q.x;
  76.                 if(!vis[newx][newy])push();
  77.             }
  78.             else {
  79.                 newx=q.x;
  80.                 newy=B;
  81.                 if(!vis[newx][newy])push();
  82.             }
  83.        }
  84.     }
  85.     return -1;
  86. }
  87. int main(){
  88.     scanf("%d",&N);
  89.     while(N--){
  90.         scanf("%d%d%d",&A,&B,&C);
  91.         scanf("%d%d%d",&x,&y,&z);
  92.         printf("%d\n",bfs());
  93.         memset(vis,0,sizeof(vis));
  94.         f=r=0;
  95.     }
  96.    return 0;
  97. }

这道题目其实就是对解答图的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)的主要内容,如果未能解决你的问题,请参考以下文章

NYOJ21.三个水杯-初始态到目标态的最少次数-经典BFS

nyoj 21 三个水杯

nyoj 21 三个水杯

nyist_21(三个水杯)(BFS)

NYOJ-三个水杯

三个水杯(BFS)