poj1606 Jugs(BFS)

题目链接:http://poj.org/problem?id=1606

题目大意:有A,B两个水壶和无限的水,可以通过6种操作使得B水壶的水量刚好为N,输出满足题意的任意一种操作顺序。

六种操作:

①把A水壶加满

②把B水壶加满

③把A水壶的水全部倒掉

④把B水壶的水全部倒掉

⑤把A水壶里的水全部倒入B水壶中,溢出的水留在A水壶内

⑥把B水壶里的水全部倒入B水壶中,溢出的水留在B水壶内

题目思路:通过6种操作不断尝试使得,B水壶的水恰好等于N。利用宽度优先搜索,记录A和B内的水量的状态,对每种状态执行6种操作,出现过的状态不必再执行(没有意义),每次之前操作需要记录之前的操作,可以用指针来记录。当B水量等于N时,宽度优先搜索结束。记录的操作是反的,因此可以用一个stack来存,最后打印stack内的元素。

注意:利用指针记录地址,不要直接new,定义一个数组,取它的地址就行了,避免内存浪费。

AC代码:

#include <cstdio>
#include <cstring>
#include <algorithm>
#include <queue>
#include <stack>
using namespace std;
const int MAXN = 1e5+10;
const int CAP = 1010;
struct node{
	int a,b;//A水壶和B水壶现在的水量
	int op;//现在需要执行操作
	node* pre;//记录上一次操作
};
int vis[CAP][CAP];
queue<node> q;
stack<int> s;

node tree[MAXN];

int n,a,b;
node* bfs(){
	memset(vis,0,sizeof(vis));
	for(int i=0;i<MAXN;i++)
		tree[i].pre=NULL;
	//初始时A和B内水都是0,需要执行6种操作
	while(!q.empty()) q.pop();
	tree[0]=(node){0,0,1,NULL};
	tree[1]=(node){0,0,2,NULL};
	tree[2]=(node){0,0,3,NULL};
	tree[3]=(node){0,0,4,NULL};
	tree[4]=(node){0,0,5,NULL};
	tree[5]=(node){0,0,6,NULL};
	q.push(tree[0]);
	q.push(tree[1]);
	q.push(tree[2]);
	q.push(tree[3]);
	q.push(tree[4]);
	q.push(tree[5]);
	int cnt=5;
	while(!q.empty()){
		node now=q.front();
		++cnt;
		tree[cnt]=q.front();
		q.pop();
		node next;
		//取地址
		next.pre=&tree[cnt];
		next.a=now.a;next.b=now.b;
		if(now.b==n)
			return &tree[cnt];
		if(now.op==1)
			next.a=a;
		else if(now.op==2)
			next.b=b;
		else if(now.op==3)
			next.a=0;
		else if(now.op==4)
			next.b=0;
		else if(now.op==5){
			//pour A to B
			if(now.b!=b){
				//B水壶的水溢出了
				if(now.a+now.b>b){
					next.b=b;
					next.a=now.a+now.b-b;
				}else{
					next.b=now.a+now.b;
					next.a=0;
				}
			}
		}else if(now.op==6){
			//pour B to A
			if(now.a!=a){
				//A水壶的水溢出了
				if(now.a+now.b>a){
					next.a=a;
					next.b=now.a+now.b-a;
				}else{
					next.a=now.a+now.b;
					next.b=0;
				}
			}
		}
		//执行六种操作
		for(int i=1;i<=6;i++){
			if(!vis[next.a][next.b]){
				q.push((node){next.a,next.b,i,next.pre});	
			}
		}
		//出现过的状态没必要再执行了
		vis[next.a][next.b]=1;
	}
}


void myPrint(int i){
	if(i==1)
		printf("fill A\n");
	else if(i==2)
		printf("fill B\n");
	else if(i==3)
		printf("empty A\n");
	else if(i==4)
		printf("empty B\n");
	else if(i==5)
		printf("pour A B\n");
	else if(i==6)
		printf("pour B A\n");
}

int main(){
	//freopen("d.txt","r",stdin);
	while(~scanf("%d%d%d",&a,&b,&n)){
		node* ans=bfs();
		while(ans->pre!=NULL){
			ans=ans->pre;
			s.push(ans->op);
		}
		while(!s.empty()){
			myPrint(s.top());
			s.pop();
		}
		printf("success\n");
	}
}

猜你喜欢

转载自blog.csdn.net/Rainbow_storm/article/details/84936922