题目描写叙述 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. Python 35 线程(1)线程理论、开启线程的两种方式

    一:线程理论 1 什么是线程 进程其实一个资源单位,而进程内的线程才是cpu上的执行单位 线程其实指的就是代码的执行过程2 为何要用线程   线程vs进程     1. 同一进程下的多个线程共享该进程 ...

  2. Hive搭建与简单使用

    hive搭建与简单使用(1) 标签(空格分隔): hive,mysql hive相当于编译器的组件,他并不存储数据,元数据存储在mysql中,数据则存放在hdfs中,通过hive,可以利用sql语句对 ...

  3. JAVA 中进行网络通信时,通信的程序两端要传输的对象,不仅要序列化,而且这个对象所属的类的名字要完全一样,连包的名字都得一样

    如上图项目目录,这是一个简易的QQ,客户端登录的时候要传输用户信息到服务器验证,所以两端都会用到User类的对象,但一开始我在Server端的包名是com.qq.server.common,两端的报名 ...

  4. ACM_来自不给标题的菜鸟出题组(巴什博弈+素数判定)

    来自不给标题的菜鸟出题组 Time Limit: 2000/1000ms (Java/Others) Problem Description: 大B和小b合作出一道程序设计月赛的题,他们的想法是给定一 ...

  5. Foeach 时修改集合的值报错

    就是"集合已修改:可能无法执行枚举操作 foreach" 啥的, 不让我改 百度到Foreach是只读的,只供取值用,无法进行新增,修改,删除(仅引用,实际待验证) 解决办法:将F ...

  6. Android MediaRecorder自定义分辨率

    Android MediaRecorder自定义分辨率 工作这么久了,确实积累了不少东西,但都是以文档的形式存在U盘里的,为什么不写博客呢?因为懒啊!!!总感觉博客太难写了(大概是上学时候写作文恐惧症 ...

  7. Linux 与 Windows 文件互传(VMWare)

    虚拟机无桌面的Linux 与 物理机Windows 文件互传有很多种方法,现在先说一种通过共享文件夹的形式,其他方法后续再补充 1.     背景 1)        虚拟机系统:VMWare无桌面的 ...

  8. 元信息标记---meta

    位于<head></head>之间 1.设置页面关键字: <meta name="keywords" content="输入具体关键字&qu ...

  9. asp.net ajax 简单案例

    第一步先引用 scriptManager <asp:UpdatePanel ID="UpdatePanelGuanZhu" runat="server"& ...

  10. sql server 存储过程(事务,带参数声明,数据库瘦身)

    CREATE PROCEDURE procedureName (@var1 as varchar(50),@var2 as varchar(50)) --建立未发临时表 AS begin tran - ...