POJ 3414 Pots

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

题目描述:

给定三个数A、B、C,表示现有容积为A、B的两个容器,有六种操作,初始状态容器为空,问是否能够经过操作使得中间至少一个容器有C个单位液体。

因为A、B、C的大小均小于100,所以无论能否组成,尝试的最多A、B组合的情况是 100 * 100 , 求最小的步数,直接BFS即可,可以用哈希判重。找到过,往回输出步骤。

<span style="font-size:18px;">#include<cstdio>
#include<iostream>
#include<string>
#include<cstring>
#include<queue>
using namespace std ;

const int MAXM = 1e5 ;
const int MAXN = 1e4 + 10 ;
int A, B, C ;
bool used[MAXM] ;
int state[MAXN] ; //FILLa, b; DROPa, b; POURa,b, b,a(1 ~ 6)
int res[MAXN] ;
int pos, cur ;
string pri[7] = {"", "FILL(1)", "FILL(2)", "DROP(1)", "DROP(2)", "POUR(1,2)", "POUR(2,1)"} ; 
//
struct node{
	int num, aa, bb, point ;
}rec[MAXN] ;

//
void setValue(int a1, int a2, int a3, int a4){
	rec[cur].num = a1 ;
	rec[cur].aa = a2 ;
	rec[cur].bb = a3 ;
	rec[cur].point = a4 ;
}
//
void cal(){
	int p ;
	pos = -1, cur = 0 ;
	memset(used, false, sizeof(used)) ;
	setValue(0, 0, 0, 0) ;
	used[0] = true ;
	pos++ ;
	p = -1 ;
	while(  pos != -1 ){
		p++ ;
		int vp = p ;
		int vv = rec[p].num ;
		int va = rec[p].aa ;
		int vb = rec[p].bb ;
		pos-- ;
		//
		if( va == C || vb == C ){
			cout << vv << endl ;
			int tt = 0 ;
			res[tt++] = state[p] ;
			while( rec[p].point != 0 ){
				res[tt++] = state[rec[p].point] ;
				p = rec[p].point ;
			}
			for( int i = tt-1; i >= 0; i-- ){
				cout << pri[res[i]] << endl ;
			}
			return ;
		}
		//
		int tmp1, tmp2 ;
		//FILL
		tmp1 = 105 * A + vb ;
		if( !used[tmp1] ){
			used[tmp1] = true ;
			cur++, pos++ ;
			state[cur] = 1 ;
			setValue(vv+1, A, vb, vp) ;
		}
		tmp2 = 105 * va + B ;
		if( !used[tmp2] ){
			used[tmp2] = true ;
			cur++, pos++ ;
			state[cur] = 2 ;
			setValue(vv+1, va, B, vp) ;
		}
		//DROP
		tmp1 = vb ;
		if( !used[tmp1] ){
			used[tmp1] = true ;
			cur++, pos++ ;
			state[cur] = 3 ;
			setValue(vv+1, 0, vb, vp) ;
		}
		tmp2 = 105 * va ;
		if( !used[tmp2] ){
			used[tmp2] = true ;
			cur++, pos++ ;
			state[cur] = 4 ;
			setValue(vv+1, va, 0, vp) ;
		}
		//POUR
		if( vb + va < B ){
			tmp1 = vb + va ;
			if( !used[tmp1] ){
				used[tmp1] = true ;
				cur++, pos++ ;
				state[cur] = 5 ;
				setValue(vv+1, 0, va+vb, vp) ;
			}
		}else{
			tmp1 = 105 * (va+vb-B) + B ; 
			if( !used[tmp1] ){
				used[tmp1] = true ;
				cur++, pos++ ;
				state[cur] = 5 ;
				setValue(vv+1, va+vb-B, B, vp) ;
			}
		}
		//
		if( vb + va < A ){
			tmp2 =  105 * (va+vb) ;
			if( !used[tmp2] ){
				used[tmp2] = true ;
				cur++, pos++ ;
				state[cur] = 6 ;
				setValue(vv+1, va+vb, 0, vp) ;
			}
		}else{
			tmp2 = 105 * A + (va+vb-A) ; 
			if( !used[tmp2] ){
				used[tmp2] = true ;
				cur++, pos++ ;
				state[cur] = 6 ;
				setValue(vv+1, A, va+vb-A, vp) ;
			}
		}
	}
	cout << "impossible" << endl ;
}
//
int main(){
	/freopen("1234.txt", "r", stdin) ;
	while( cin >> A >> B >> C ){
		if( A == C || B == C ){
			cout << 1 << endl ;
			if( A == C ){
				cout << "FILL(1)" << endl ;
			}else{
				cout << "FILL(2)" << endl ;
			}
		}else{
			cal() ;
		}
	}
	return 0 ;
}</span>


评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值