kuangbin专题 专题一 简单搜索 Pots POJ - 3414

Pots POJ - 3414

题目链接:https://vjudge.net/problem/POJ-3414

题意:给你两个杯子,分别容量为A(1),B(2)和一个C,C是需要经过下列操作,得到的一个升数。
(1) FILL(i) :把编号为i的杯子中水灌满
(2)DROP(i):把编号为i的杯子中水全部倒了
(3)POUR(i,j):把编号为i的杯子中的水倒入编号为j的杯子中,如果编号j杯子中水满了,编号i杯子水就不继续倒了
问:能不能经过有限次(1)(2)(3)操作,得到A,B中其中一个满足C升的水就可以,可以的话输出最少次数并把操作输出,否则输出“impossble”

思路:最少,容易想到bfs,加上倒水过程的模拟,也就6种情况,模拟操作预处理之后,后面会变得很好写,其中的过程,看代码注释吧。
补:我们可以把A,B中升数情况给记录下,出现过的<A,B>就不需要再次bfs了,不然应该会TLE

#include <iostream>
#include <cstring>
#include<vector>
#include<string>
#include <cmath>
#include <map>
#include <queue>
#include <algorithm>
using namespace std;

#define inf (1LL << 31) - 1
#define rep(i,j,k) for(int i = (j); i <= (k); i++)
#define rep__(i,j,k) for(int i = (j); i < (k); i++)
#define per(i,j,k) for(int i = (j); i >= (k); i--)
#define per__(i,j,k) for(int i = (j); i > (k); i--)

int A_L, B_L, C_L;

//六种操作,都先预处理好
string op[6] = { "FILL(1)", "FILL(2)", "DROP(1)", "DROP(2)",
				"POUR(1,2)", "POUR(2,1)" };
//其实算一个类用
struct node{

	int A,B; //A,B杯子中水升数情况
	vector<string > str; //记录操作
//	int l;
	node(int a = 0, int b = 0){ A = a; B = b; }

	void Fill(int num){ //(1)操作处理
		if (num == 1) A = A_L;
		else B = B_L;
	}
		
	void Drop(int num){ //(2)操作处理
		if (num == 1) A = 0;
		else B = 0;
	}

	void Pour(int num){ //(3)操作处理
		if (num == 1){
			int tmp = A;
			A -= (A >= B_L - B ? (B_L - B) : A);
			B = (tmp >= B_L - B ? B_L : B + tmp);
		}
		else{
			int tmp = B;
			B -= (B >= A_L - A ? (A_L - A) : B);
			A = (tmp >= A_L - A ? A_L : A + tmp);
		}
	}

};

void fun(string str){
	cout << str << endl;
}

void bfs(){

	map<pair<int, int>, bool> mp;  //记录<A,B>的情况

	node init;
	/*
	pair<int,int > p (init.A, init.B);
	mp[p] = true;
	*/
	
	queue<node> que;
	que.push(init);

	while (!que.empty()){

		node key = que.front();
		que.pop();

		pair<int, int> o( key.A, key.B ); 
		if (mp[o]) continue; //判断这个<A,B>有误出现过,出现了就不继续下去了
		mp[o] = true; //没出现过,标记一下
		
		//六种情况
		rep(p, 1, 6){
			
			node tmp = key;

			if (p == 1) tmp.Fill(1),tmp.str.push_back(op[0]);
			else if (p == 2) tmp.Fill(2), tmp.str.push_back(op[1]);
			else if (p == 3) tmp.Drop(1), tmp.str.push_back(op[2]);
			else if (p == 4) tmp.Drop(2), tmp.str.push_back(op[3]);
			else if (p == 5) tmp.Pour(1), tmp.str.push_back(op[4]); //pour(1,2)
			else if (p == 6) tmp.Pour(2), tmp.str.push_back(op[5]); //pour(2,1)
			
			//其中一个满足即可
			if (tmp.A == C_L || tmp.B == C_L){  
				cout << (int)tmp.str.size() << endl;
				
				//遍历tmp的vector
				for_each(tmp.str.begin(), tmp.str.end(), fun);

				return;
			}

			o = make_pair(tmp.A, tmp.B); //也是判断下新的<A,B>是否出现过
			if (!mp[o]) que.push(tmp); //出现过,不再压入队列
		}
	}

	//无法得出C
	cout << "impossible" << endl;

}

int main(){

	ios::sync_with_stdio(false);
	cin.tie(0);

	cin >> A_L >> B_L >> C_L; //记录A的最大容量,B的最大容量,标准C
	bfs();

	return 0;
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值