题目描写叙述 Description

有两个无刻度标志的水壶。分别可装 x 升和 y 升 ( x,y 为整数且均不大于 100 )的水。

设另有一水 缸,可用来向水壶灌水或接从水壶中倒出的水, 两水壶间,水也能够相互倾倒。已知 x 升壶为空 壶, y 升壶为空壶。问怎样通过倒水或灌水操作。 用最少步数能在x或y升的壶中量出 z ( z ≤ 100 )升的水 来。

输入描写叙述 Input Description

一行,三个数据。分别表示 x,y 和 z;

输出描写叙述 Output Description

一行,输出最小步数 ,假设无法达到目标,则输出"impossible"

例子输入 Sample Input

3 22 1

例子输出 Sample Output

14

数据范围及提示 Data Size & Hint

此题数据太弱了,DFS略微剪枝下都能过,无语
倒水一共同拥有6种策略:
操作1:装满a桶

操作2:装满b桶

操作3:清空a桶

操作4:清空b桶

操作5:将B桶中的水倒入A桶

操作6:将A桶的水倒入B桶
每种策略在推断条件后模拟一遍就OK了。只是要注意判重
无论是DFS还是BFS。强调它的判重仅仅须要数组就够了,不是必需像ZFX童鞋那样用STL的set。因为x,y<=100。最多有10000种状态。数组不会爆
1、DFS
这里判重数组不仅要保存该结点是否訪问过。并且要记录该结点的步数(即解的好坏),便于为后面循环求得最优解
#include <stdio.h>
#define MAXN 200
#define INF 10000000
int f[MAXN][MAXN],a,b,z; //f[x][y]=达到A桶内水量为x,B桶内水量为y的状态所需步骤数
void dfs(int x,int y,int step) //x=A桶内水量,y=B桶内水量,step=当前步骤数
{
if(f[x][y]!=0&&step+1>=f[x][y]) return; //当前状态已经有解且如今的解一定比过去的解更差时,退出
f[x][y]=step+1; //更新当前状态所需最少步骤数
dfs(x,0,step+1); //1、清空B桶
dfs(0,y,step+1); //2、清空A桶
dfs(x,b,step+1); //3、装满B桶
dfs(a,y,step+1); //4、装满A桶
//5、将B桶倒入A桶
if(x+y<=a)
dfs(x+y,0,step+1);//(i)B桶倒空后A桶不会溢出
else
dfs(a,x+y-a,step+1); //(ii)B桶倒空后A桶会溢出,故B桶中有残留
//6、将A桶倒入B桶
if(x+y<=b)
dfs(0,x+y,step+1);//(i)A桶倒空后B桶不会溢出
else
dfs(x+y-b,b,step+1); //(ii)A桶倒空后B桶会溢出,故A桶中有残留
}
int main()
{
int i,j,ans=INF;
scanf("%d%d%d",&a,&b,&z);
dfs(0,0,0);
for(i=0;i<=a;i++)
if(f[i][z]!=0)
if(f[i][z]<ans)
ans=f[i][z]; //遍历全部B桶中达到水量z的情况。获得最优解
for(i=0;i<=b;i++)
if(f[z][i]!=0)
if(f[z][i]<ans)
ans=f[z][i]; //遍历全部B桶中达到水量z的情况,获得最优解
if(ans==INF) printf("impossible\n");
else printf("%d\n",ans-1);
return 0;
}

2、BFS
BFS做法略微复杂些。只是和DFS殊途同归,依据BFS的性质。BFS终于搜索出的结果就是最优解,判重数组仅仅需保存每一个结点是否訪问过就能够了,另外BFS的判重很重要。否则BFS将进入死循环(我刚開始的代码就是这样,调了一个多小时。ORZ)
#include <stdio.h>
#include <stdlib.h>
#include <queue>
#define MAXN 110
using namespace std;
int a,b,z,f[MAXN][MAXN]; //目标是取z L水
struct cup
{
int x; //x桶(大桶)中的水量
int y; //y桶(小桶)中的水量
int sol; //sol=量出的水量
int step; //step=倒水次数
}first,now;
queue<cup>Q;
void extend(cup in) //扩展结点
{
if(f[in.x][in.y]!=0) return;
f[in.x][in.y]++;
in.step++;
cup p=in;
//操作1:装满a桶
p.x=a;
Q.push(p);
//操作2:装满b桶
p=in;
p.y=b;
Q.push(p);
//操作3:清空a桶
p=in;
p.x=0;
Q.push(p);
//操作4:清空b桶
p=in;
p.y=0;
Q.push(p);
//操作5:将B桶中的水倒入A桶
p=in;
if(in.x+in.y<=a) //(i)B桶倒空后A桶不会溢出
{
p.x=in.x+in.y;
p.y=0;
Q.push(p);
}
else //(ii)B桶倒空后A桶会溢出,故B桶中有残留
{
p.x=a;
p.y=in.x+in.y-a;
Q.push(p);
}
//操作6:将A桶的水倒入B桶
p=in;
if(in.x+in.y<=b) //(i)A桶倒空后B桶不会溢出
{
p.y=in.x+in.y;
p.x=0;
Q.push(p);
}
else //(ii)A桶倒空后B桶会溢出,故A桶中有残留
{
p.y=b;
p.x=in.x+in.y-b;
Q.push(p);
}
}
void bfs()
{
Q.push(first);
while(!Q.empty())
{
now=Q.front();
Q.pop(); //取出队首状态
if(now.x==z||now.y==z)
{
printf("%d\n",now.step);
exit(0);
}
extend(now);
}
printf("impossible\n");
}
int main()
{
scanf("%d%d%d",&a,&b,&z);
first.step=0;
first.x=0;
first.y=0;
bfs();
return 0;
}

 

[Wikioi 1226]倒水问题的更多相关文章

  1. 广度优先搜索 cdoevs 1226 倒水问题

    cdoevs 1226 倒水问题  时间限制: 1 s  空间限制: 128000 KB  题目等级 : 黄金 Gold   题目描述 Description 有两个无刻度标志的水壶,分别可装 x 升 ...

  2. codevs 1226 倒水问题

    1226 倒水问题 时间限制: 1 s 空间限制: 128000 KB 题目等级 : 黄金 Gold   题目描述 Description 有两个无刻度标志的水壶,分别可装 x 升和 y 升 ( x, ...

  3. CodeVS 1226 倒水问题【DFS/BFS】

    题目描述 Description 有两个无刻度标志的水壶,分别可装 x 升和 y 升 ( x,y 为整数且均不大于 100 )的水.设另有一水 缸,可用来向水壶灌水或接从水壶中倒出的水, 两水壶间,水 ...

  4. 洛谷P1432 倒水问题(CODEVS.1226)

    To 洛谷.1432 倒水问题 题目背景 In the movie "Die Hard 3", Bruce Willis and Samuel L. Jackson were co ...

  5. 倒水问题 (codevs 1226) 题解

    [问题描述] 有两个无刻度标志的水壶,分别可装x升和y升 ( x,y 为整数且均不大于100)的水.设另有一水缸,可用来向水壶灌水或接从水壶中倒出的水, 两水壶间,水也可以相互倾倒.已知x升壶为空壶, ...

  6. BZOJ 1226: [SDOI2009]学校食堂Dining

    1226: [SDOI2009]学校食堂Dining Time Limit: 10 Sec  Memory Limit: 259 MBSubmit: 730  Solved: 446[Submit][ ...

  7. POJ 1226 后缀数组

    题目链接:http://poj.org/problem?id=1226 题意:给定n个字符串[只含大小写字母],求一个字符串要求在n个串或者他们翻转后的串的出现过.输出满足要求的字符串的长度 思路:根 ...

  8. 【wikioi】1041 Car的旅行路线

    题目链接 算法:最短路(数据弱,Floyd也能过) 惨痛的教训:此题我至少提交了20次,原因在于= =太草率和粗心了,看到那个多少组数据以为是城市的数量,导致数组开得小小的= =.(对不起,wikio ...

  9. 【wikioi】1040 统计单词个数

    题目链接 算法:划分型DP PS:被卡过3天.日期:2013-10-10 ~ 2013-10-12 18:52:48 这题是我提交了13次AC= =汗= = 题目描述: 给出一个长度不超过200的由小 ...

随机推荐

  1. php的string编码类型

    在php中字符编码转换我们一般会用到iconv与mb_convert_encoding进行操作,但是mb_convert_encoding在转换性能上比iconv要差很多哦.string iconv ...

  2. Aviator

    Aviator 简介¶ Aviator是一个高性能.轻量级的java语言实现的表达式求值引擎,主要用于各种表达式的动态求值.现在已经有很多开源可用的java表达式求值引擎,为什么还需要Avaitor呢 ...

  3. python3+request接口自动化框架中自动发送邮件

    在上一篇中的自动化框架中没有放上自动发送测试结果到邮箱的功能,在这篇文章中在补一下,哈哈 1.上一篇的代码就不在一一介绍了,本篇只介绍发送邮件的功能代码 2.在public common 文件夹中创建 ...

  4. jq中append()、prepend()、after()、before()的区别

    jq中append().prepend().after().before()的区别详解 .append() - 在被选元素的结尾插入内容(内容的结尾,比如说有个a标签,则是在</a>这个标 ...

  5. for 循环的中的i

    for循环中的i,如果倒过来判断从某数一直到0,一定不能用unsigned int类型的i,因为unsigned int不可能小于0,当i=0后,i--将达到最大的unsigned int,依旧> ...

  6. JavaScript alert()函数的使用方法

    这里向大家简单介绍一下JavaScript alert()函数的使用,alert--弹出消息对话框,并且alert消息对话框通常用于一些对用户的提示信息. JavaScript alert()函数 a ...

  7. 树莓派-USB存储设备自动挂载

    简单介绍实现命令行下USB存储设备自动挂载的方法,Linux gnome/kde窗口环境下有移动存储的管理程序,可以实现自动挂载移动存储设备,但是在命令行下 通常需要用mount命令手动挂载USB存储 ...

  8. Elasticsearch中的segment理解

    https://blog.csdn.net/smithallenyu/article/details/52789872 参照图 https://www.cnblogs.com/smile361/p/7 ...

  9. SLAM: Orb_SLAM中的ORB特征

    原文链接:什么是ORB 关于Orb特征的获取:参考 最新版的OpenCV中新增加的ORB特征的使用 ORB是是ORiented Brief 的简称,对Brief的特定性质进行了改进. ORB的描述在下 ...

  10. 08--C++拷贝构造函数详解

    C++拷贝构造函数详解 一. 什么是拷贝构造函数 首先对于普通类型的对象来说,它们之间的复制是很简单的,例如: [c-sharp] view plain copy int a = 100; int b ...