Pots POJ - 3414

该博客主要介绍了一个利用BFS(广度优先搜索)解决PotsPOJ-3414题目的过程。代码中定义了六种操作,并通过一个队列进行状态的遍历。当找到目标状态时,返回距离并使用DFS(深度优先搜索)回溯输出操作路径。若未找到解决方案,则返回'Impossible'。
摘要由CSDN通过智能技术生成

Pots POJ - 3414

题目

思路:直接bfs不过还要存储路径

具体代码如下

#include<iostream>
#include<queue>
#include<stack>
#include<cstdio>
#include<cstring>

using namespace std;

const int N = 1010;

char * res[] = {"FILL(1)", "FILL(2)", "DROP(1)", "DROP(2)", "POUR(1,2)", "POUR(2,1)"};
//对应六种操作

struct water{ //a,b存水量, pre存前驱, s存操作
	int a, b, pre; 
	char *s;
};

int n, m, k, cnt; //cnt用来存储point中的下标
int dis[N][N];
water point[100010]; //用来存储数据以便输出路径

int bfs(){
	
	queue<water> q;
	water xx;
	xx.a = 0, xx.b = 0, xx.s = "";
	q.push(xx);
	dis[0][0] = 0; //从0,0开始
	
	while(q.size()){
		water t = q.front();
		q.pop();
		point[cnt++] = t;
		if(t.a == k || t.b == k) return dis[t.a][t.b]; //如果搜到就返回
		
		for(int i=0; i<6; ++i){
			water t2 = t;
			if(i == 0) t2.a = n;//操作一a瓶加满水
			else if(i == 1) t2.b = m;//操作二b瓶加满水
			else if(i == 2) t2.a = 0;//操作三a瓶水倒掉
			else if(i == 3) t2.b = 0;//...
			else if(i == 4){//操作5把a瓶中的水倒入b瓶
				int amount = min(m, t2.a + t2.b) - t2.b;//amount表示可以倒的最多水量
				//如果b瓶子体积大于a瓶中的水+b瓶中的水amount = a瓶中的水,反之amount = b瓶总体积-b瓶中水的体积
				t2.a -= amount;
				t2.b += amount;
			}else{
				int amount = min(n, t2.b + t2.a) - t2.a;//同上
				t2.b -= amount;
				t2.a += amount;
			}
			
			if(dis[t2.a][t2.b] == -1){ //更新距离
				dis[t2.a][t2.b] = dis[t.a][t.b] + 1;
				t2.s = res[i];
				t2.pre = cnt - 1; //记录前驱
				q.push(t2);
			}
		}
	}
	
	return -1;
}

void dfs(int cnt2){
	//输出用栈,也可以写一个深搜
	char * stk[N];
	int i = 0;
	while(cnt2){
		stk[i++] = point[cnt2].s;
		cnt2 = point[cnt2].pre;
	}
	i -= 1;
	while(i >= 0){
		char * t = stk[i--];
		printf("%s\n", t);
	}
}


int main(){
	
	scanf("%d%d%d", &n, &m, &k);
	memset(dis, -1, sizeof dis);
	int ans = bfs();
	
	
	if(ans == -1) puts("impossible");
	else{
		printf("%d\n", ans);
		dfs(cnt -1);
	}
	
	return 0;
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值