<题目链接>

题目大意:

有两个容量的空杯子,能够对这两个空杯子进行三种操作:

分别是fill(a),装满a杯子;

drop(a),倒空a杯子;

pour(a,b),将a杯子中的水倒入b杯子中;

现在问你,是否能够通过这三种操作,使得这两个杯子中至少有一个杯子中含有c体积的水,如果不行,输出“impossible”,如果可以,输出操作的步数,以及每一步的具体操作。

解题分析:

此题与一道输出路径的很相像,只不过那道题是输出每一次操作对应的点的状态,而此题是要输出具体的操作。不难想到,我们依然可以记录下BFS路径上点的状态,然后根据这个点和上一个点的状态差距推导出它们之间的具体操作。

#include <cstdio>
#include <cstring> int v[],m; const int maxn=;
int vis[][];
int flag; struct node{
int val[];
int step;
int pre; //记录上一个点在que[]数组中的位置
node(int a=,int b=,int c=,int d=-){
val[]=a,val[]=b,step=c,pre=d;
}
}que[maxn]; void fill(node &now,int a){
now.val[a]=v[a];
} void drop(node &now,int a){
now.val[a]=;
} void pour(node &now,int a,int b){
int sum=now.val[a]+now.val[b];
if(sum>v[b]){
now.val[b]=v[b];
now.val[a]=sum-v[b];
}
else{
now.val[b]=sum;
now.val[a]=;
}
} void print(node tmp){ //根据相邻两个点的状况来推断操作
if(tmp.pre!=-){
print(que[tmp.pre]);
}
if(tmp.pre!=-){ //如果这个点和上一个点之间有操作,就可以将这个操作求出来
node prenode=que[tmp.pre];
node cal=prenode;
pour(cal,,);
if(tmp.val[]==v[]&&tmp.val[]==prenode.val[]){
printf("FILL(1)\n");
}
else if(tmp.val[]==v[]&&tmp.val[]==prenode.val[]){
printf("FILL(2)\n");
}
else if(tmp.val[]==&&tmp.val[]==prenode.val[]){
printf("DROP(1)\n");
}
else if(tmp.val[]==&&tmp.val[]==prenode.val[]){
printf("DROP(2)\n");
}
else if(cal.val[]==tmp.val[]&&cal.val[]==tmp.val[]){
printf("POUR(1,2)\n");
}
else{
printf("POUR(2,1)\n");
}
}
} void bfs(){
memset(vis,,sizeof(vis));
int front=,end=;
vis[][]=;
que[end++]=node(,,,-);
while(front<end){
node now=que[front];
front++;
if(now.val[]==m||now.val[]==m){
flag=true;
printf("%d\n",now.step);
print(now);
return;
}
for(int i=;i<=;i++){ //装满
node tmp=now; //注意,这里为了防止now发生改变,从而对后面的操作产生影响,所以这里是对tmp进行操作
fill(tmp,i);
if(!vis[tmp.val[]][tmp.val[]]){
vis[tmp.val[]][tmp.val[]]=;
que[end++]=node(tmp.val[],tmp.val[],tmp.step+,front-);
}
}
for(int i=;i<=;i++){ //倒空
node tmp=now;
drop(tmp,i);
if(!vis[tmp.val[]][tmp.val[]]){
vis[tmp.val[]][tmp.val[]]=;
que[end++]=node(tmp.val[],tmp.val[],tmp.step+,front-);
}
}
for(int i=;i<=;i++){ //i向j注水
for(int j=;j<=;j++){
if(i==j)continue;
node tmp=now;
pour(tmp,i,j);
if(!vis[tmp.val[]][tmp.val[]]){
vis[tmp.val[]][tmp.val[]]=;
que[end++]=node(tmp.val[],tmp.val[],tmp.step+,front-);
}
}
}
}
} int main(){
while(scanf("%d %d %d",&v[],&v[],&m)!=EOF){
flag=false;
bfs();
if(!flag){
printf("impossible\n");
}
}
return ;
}

2018-08-29

POJ 3414 Pot (输出路径)【BFS】的更多相关文章

  1. Pots POJ - 3414【状态转移bfs+回溯】

    典型的倒水问题: 即把两个水杯的每种状态视为bfs图中的点,如果两种状态可以转化,即可认为二者之间可以连一条边. 有3种倒水的方法,对应2个杯子,共有6种可能的状态转移方式.即相当于图中想走的方法有6 ...

  2. POJ 3414 Pots 记录路径的广搜

    Description You are given two pots, having the volume of A and B liters respectively. The following ...

  3. HDU 1043 Eight 【经典八数码输出路径/BFS/A*/康托展开】

    本题有写法好几个写法,但主要思路是BFS: No.1 采用双向宽搜,分别从起始态和结束态进行宽搜,暴力判重.如果只进行单向会超时. No.2 采用hash进行判重,宽搜采用单向就可以AC. No.3 ...

  4. 【POJ - 3414】Pots(bfs)

    Pots 直接上中文 Descriptions: 给你两个容器,分别能装下A升水和B升水,并且可以进行以下操作 FILL(i)        将第i个容器从水龙头里装满(1 ≤ i ≤ 2); DRO ...

  5. Pots(POJ - 3414)【BFS 寻找最短路+路径输出】

    Pots(POJ - 3414) 题目链接 算法 BFS 1.这道题问的是给你两个体积分别为A和B的容器,你对它们有三种操作,一种是装满其中一个瓶子,另一种是把其中一个瓶子的水都倒掉,还有一种就是把其 ...

  6. 广搜+输出路径 POJ 3414 Pots

    POJ 3414 Pots Time Limit: 1000MS   Memory Limit: 65536K Total Submissions: 13547   Accepted: 5718   ...

  7. poj 3414 Pots 【BFS+记录路径 】

    //yy:昨天看着这题突然有点懵,不知道怎么记录路径,然后交给房教了,,,然后默默去写另一个bfs,想清楚思路后花了半小时写了120+行的代码然后出现奇葩的CE,看完FAQ改了之后又WA了.然后第一次 ...

  8. (poj)3414 Pots (输出路径的广搜)

    Description You are given two pots, having the volume of A and B liters respectively. The following ...

  9. POJ 3414 Pots【bfs模拟倒水问题】

    链接: http://poj.org/problem?id=3414 http://acm.hust.edu.cn/vjudge/contest/view.action?cid=22009#probl ...

随机推荐

  1. 卷积神经网络(CNN)学习笔记1:基础入门

    卷积神经网络(CNN)学习笔记1:基础入门 Posted on 2016-03-01   |   In Machine Learning  |   9 Comments  |   14935  Vie ...

  2. AJAX请求头Content-type

    发送json格式数据 xhr.setRequestHeader("Content-type","application/json; charset=utf-8" ...

  3. SSM框架报错分析(一)——There is no getter for property named 'XXX' in 'class java.lang.String'

    一.发现问题 <select id="queryStudentByNum" resultType="student" parameterType=&quo ...

  4. Delphi中的动态包,有详细建立包的步骤(答案很简单:因为包的功能强大)

    为什么要使用包? 答案很简单:因为包的功能强大.设计期包(design-time package)简化了自定义组件的发布和安装:而运行期包(run-time package)则更是给传统的程序设计注入 ...

  5. 在Asp.Net Core中使用中间件保护非公开文件

    在企业开发中,我们经常会遇到由用户上传文件的场景,比如某OA系统中,由用户填写某表单并上传身份证,由身份管理员审查,超级管理员可以查看. 就这样一个场景,用户上传的文件只能有三种人看得见(能够访问) ...

  6. git免密配置

    1.在git安装目录下双击bash.exeC:\DevTools\Git\bin 2.在弹出窗口内输入,回车,回车ssh-keygen -t rsa -C "542113457@qq.com ...

  7. VS C# xamarin 开发android 调试正常 发布分发后运行闪退出错

    我强烈推荐大家如果不是很有必要就不要引用一些.NET STD的库,比如json库newtonsoft.JSON,直接引用官方的system.Json就足够了,否则会导致体积变得巨大 好了废话不多说,这 ...

  8. mongodb数据库集群及sharding分片配置

    复制集群的配置 1.安装mongodb数据库 在主节点和从节点上都安装mongodb # rpm -ivh mongo-10gen-2.4.6-mongodb_1.x86_64.rpm mongo-1 ...

  9. PL/SQL第五章 Order by排序

    -- 排序 -- 1.列明排序 -- 2.别名排序 -- 3.列位置排序(当使用union,union all,intersect,minus集合操作,列明不同,但希望排序) SELECT deptn ...

  10. 【前端】js截取or分割字符串的常见方法

    1.截取字符串 分割字符串方法 1.charAt(): 没有一种有别于字符串类型的字符数据类型,所以返回的字符是长度为 1 的字符串 例如:var str="Hello world!&quo ...