week2作业2-pour water

题意

倒水问题 “fill A” 表示倒满A杯,"empty A"表示倒空A杯,“pour A B” 表示把A的水倒到B杯并且把B杯倒满或A倒空。输入包含多组数据。每组数据输入 A, B, C 数据范围 0 < A <= B 、C <= B <=1000 、A和B互质.你的程序的输出将由一系列的指令组成。这些输出行将导致任何一个罐子正好包含C单位的水。每组数据的最后一行输出应该是“success”。输出行从第1列开始,不应该有空行或任何尾随空格。

思路

这是一道典型的隐式图问题,对于每个杯子我们有6中备选操作让它改变状态,即相当于一个满6叉树,对这颗树进行遍历寻找到所求的C,这里采用的是广搜,边计算下一层的点,边进行查找。
对于存取路径,这里采用的是储存常量数组索引法,没进行一次操作就将索引加到字符串尾,输出时只需要将字符串按字符遍历即可

总结

这里的队列实现还可以用非队列形式解决,开一个大数组利用两个游标的相对位置判断队列是否空,达到同样的作用

代码

#include<stdio.h>
#include<string>
#include<string.h>
#include<iostream>
#include<queue>
using namespace std;
int ca,cb,n;
bool vis[4000][4000];
struct cup{
	int a,b;
	string s;//存储路径 
	cup(){}
	cup(int qa,int qb,string ss){
		a=qa;
		b=qb;
		s=ss;
	}
};
queue<cup> qu;
string caozuo[6]={"fill A","empty A","fill B","empty B","pour A B","pour B A"};
void bfs(){
	qu.push(cup(0,0,string()));
	vis[0][0]=1;
	while(!qu.empty()){
		int a=qu.front().a;
		int b=qu.front().b;
		string s=qu.front().s;
		qu.pop();
		if(b==n||a==n){ //特判终点 
			for(int i=0;i<s.size();i++){//输出路径 
				cout<<caozuo[s[i]-48]<<endl;
			}
			cout<<"success"<<endl;
			return;
		}
		if(!vis[ca][b]){// fill A 
			qu.push(cup(ca,b,s+"0"));
			vis[ca][b]=1;
		}
		if(!vis[0][b]){//empty A
			qu.push(cup(0,b,s+"1"));
			vis[0][b]=1;
		}
		if(!vis[a][cb]){//fill B
			qu.push(cup(a,cb,s+"2"));
			vis[a][cb]=1;
		}

		if(!vis[a][0]){//empty B
			qu.push(cup(a,0,s+"3"));
			vis[a][0]=1;
		}
		int c=a+b>cb?cb:a+b;//pulll A B
		if(!vis[a+b-c][c]){//B中水量可能满也可能不满 
			qu.push(cup(a+b-c,c,s+"4"));
			vis[a+b-c][c]=1;
		}
		c=a+b>ca?ca:a+b;  //pull B A 
		if(!vis[c][a+b-c]){//A中水量可能满也可能不满 
			qu.push(cup(c,a+b-c,s+"5"));
			vis[c][a+b-c]=1;
		}

	}
	return;
}
int main() {
    while(~scanf("%d%d%d",&ca,&cb,&n)){
    	memset(vis,0,sizeof(vis));
    	while(!qu.empty())qu.pop();//多组数据将队列置空 
    	bfs();
	}
    return 0;
}

发布了20 篇原创文章 · 获赞 3 · 访问量 463

猜你喜欢

转载自blog.csdn.net/qq_44893580/article/details/104644693