zoukankan      html  css  js  c++  java
  • 水杯倒水问题

      1 #include <stdio.h>
      2  #include <stdlib.h>
      3  #include <string.h>
      4  /*下面定义结点的类型*/
      5  #define Min(a,b) ((a>b)?b:a)
      6  //宏定义的操作符Min作用 取最小值; 
      7  const int MAX=1010;
      8  //解答树的结点最多 
      9  typedef struct Node
     10  {
     11      int v[3];//三个杯子的剩余水量;
     12      int fa;//第一次访问到这个结点是的前一个结点的下标;
     13      //通过下标可以随机访问真不错; 
     14       int last_op;//记录从上个结点到这个结点的变化方式
     15       //last_op认为是两位数字,第一位表示往外倒水的杯子
     16       //的编号,第二位表示被倒入水的杯子; 
     17      int  deepth;
     18      //记录从原始状态到这个状态变化的最少的步数;也就是解答树的深度; 
     19  }Node; 
     20  int cup_capacity[3];//存储三个杯子的容量; 
     21  int water_to_get; //存储要量出的水量; 
     22  Node  q[MAX*MAX]; //定义这么多个状态组成的数组; 用这个数组来表示队列真不错; 
     23  int vis[MAX][MAX];//两个下标分别是中杯的余量和小杯的余量; 
     24  void print_path(int destination);//函数的作用是输出从下标为0到下标为destination的结点的路径; 
     25  void bfs();//breath-first-search;广度优先遍历 ;
     26  int main()
     27  {
     28      /*首先读入三个杯子的容量和要量出的水量*/
     29      scanf("%d%d%d%d",&cup_capacity[0],&cup_capacity[1],&cup_capacity[2],&water_to_get);
     30      /*进行遍历搜索*/
     31      memset(vis,0,sizeof vis);//sizeof 对于变量名可以不用括号 表明 它并不是一个函数 ;
     32      /*
     33      memset()起初是为字符数组赋值的所以需要包含头文件string.h,
     34      但是它可以为结构体,一维数组,二维数组等赋值了 ;
     35      这里其实并不需要赋值,因为全局变量已经被初始化了; 
     36      */ 
     37      bfs();
     38      return 0; 
     39  } 
     40  void bfs()
     41  {
     42      q[0].v[0]=cup_capacity[0];
     43      q[0].v[1]=q[0].v[2]=0;
     44      q[0].fa=0;//因为第一个结点没有父节点了; 
     45      q[0].deepth=0;//也可以不写这些0;因为全局变量会自动初始化; 
     46      q[0].last_op=0;//因为是第一个结点 ;
     47      vis[q[0].v[1]][q[0].v[2]]=1;//表示这个结点已经在队列里了
     48      //如果在遇到它就不再将它放进队列了; 
     49      //上个句子也可以这么写vis[0][0]=1; 
     50      int front=0,rear=1;//模拟队列;可以实现广度优先遍历; 
     51      while(front<rear)
     52      {
     53          Node N=q[front];//当前队列中将要访问的变量;
     54          if(N.v[0]==water_to_get||N.v[1]==water_to_get||N.v[2]==water_to_get)
     55          {//如果当前结点正好就是要访问的,那么就来输出它的路径; 
     56              //首先输出需要的步数;
     57              printf("%d\n",N.deepth);
     58              //然后调用递归函数依次输出各个中间状态;
     59              print_path(front); 
     60              return;
     61          }
     62          for(int i=0;i<3;i++)//往外倒水的杯子进行枚举;
     63          {
     64              
     65              for(int j=0;j<3;j++)//被倒入水的杯子的枚举;
     66              {//i!=j;是避免了那些自己往自己里面倒水的情况发生; 
     67                  Node &IN=q[rear];
     68                  if(i==j)continue;
     69                  int amount=Min(N.v[i],cup_capacity[j]-N.v[j]);//这个是用来决定倒出水的多少
     70                  //要么倒水的杯子倒完;要么被倒入的杯子被倒满; 
     71                  for (int k=0;k<3;k++)
     72                  {
     73                      IN.v[k]=N.v[k];
     74                  }
     75                  IN.v[i]=N.v[i]-amount;//从i杯倒出amount量的水; 
     76                  IN.v[j]=N.v[j]+amount;//倒入j杯amou量的水;
     77                  //至此就产生了一个状态;然后就要看它是否已经存在于队列里面了; 
     78                  if(!vis[IN.v[1]][IN.v[2]])
     79                  {
     80                      vis[IN.v[1]][IN.v[2]]=1;
     81                      IN.fa=front;//设置父节点的下标;
     82                      IN.deepth=N.deepth+1;//设置最少步骤数;
     83                      IN.last_op=10*i+j;//记录变换的方法;
     84                      
     85                      rear++; 
     86                  }//if
     87              } //for(j)
     88          } //for(i)
     89          front++;//从队列的下一个结点向下一次考察; 
     90           
     91      }//while
     92  }
     93  void print_path(int destination)
     94  {
     95      if(q[destination].fa!=destination)
     96      {
     97          print_path(q[destination].fa);//先找到原始的元素;递归栈机制可以记得路径 
     98          int from=q[destination].last_op/10,to=q[destination].last_op%10;
     99          int num=q[q[destination].fa].v[from]-q[destination].v[from];
    100          printf("cup %d (-%d)->cup %d\n",from,num,to); 
    101      }
    102      printf("(%d,%d,%d)\n",q[destination].v[0],q[destination].v[1],q[destination].v[2]);
    103      
    104  }
  • 相关阅读:
    《Python数据挖掘入门与实践》高清中文版PDF+英文版+源码下载
    discuz 论坛配置 QQ/163 网易邮箱
    Discuz! X3 去掉内容图片提示下载方法(去除图片提示下载附件)
    HTTPS的建立过程(SSL建立安全会话的过程)
    前端开发之走进Vue.js
    优雅统计代码耗时的4种方法!
    Maven配置多个远程仓库的实现方法
    idea maven 一直报错“Could not transfer artifact ......(系统找不到指定的路径。)”
    IntelliJ IDEA为类和方法自动添加注释
    maven “mvn clean package”和“mvn clean install”有什么不同?
  • 原文地址:https://www.cnblogs.com/xiaofanke/p/2994448.html
Copyright © 2011-2022 走看看