POJ 3414 Pots BFS

题意:给你两个罐子,你可以执行以下操作:
1. FILL(i)        将罐子 i 装满水
2. DROP(i)      将罐子 i 中的水倒掉
3. POUR(i,j)    将罐子 i 中的水倒入罐子 j 中,若 i 中的容量大于 j 中的容量, 那么 i  中有剩余。
现在给出A,B两个罐子的容量,开始时A,B皆空,问能不能经过一系列操作使得A,B中有一个装有C水?
题解:

#include <queue>
#include <iostream>
using namespace std;

int a,b,c;
int vis[101][101], father[10001];
char path[10][10] = { "", "FILL(1)", "FILL(2)", "DROP(1)", "DROP(2)", "POUR(1,2)", "POUR(2,1)"};

struct State
{
	int pot1, pot2, step, oper; /* pot1 表示1中的水量, pot2 表示2中的水量, step记录到达当前状态所经历的步骤,oper为操作类型 */
} state[10001];

void print( int x ) /* 输出结果 */
{
	if ( father[x] != 0 )
		print(father[x]);
	printf("%s\n", path[state[x].oper]); 
}

int bfs()
{
	queue<int> Q;
	state[0].pot1 = 0;
	state[0].pot2 = 0;
	state[0].oper = state[0].step = father[0] = 0;
	vis[0][0] = 1;
	Q.push ( 0 );
	int cnt = 0, cur, temp;
	while ( ! Q.empty () )
	{
		cur = Q.front ();
		Q.pop ();
		if ( state[cur].pot1 == c || state[cur].pot2 == c ) /* 任意一个的容量为C则返回最后一个状态的编号 */
			return cur;
		if ( ! vis[a][state[cur].pot2] ) /* 将 1 装满 */
		{
			cnt++;
			father[cnt] = cur;
			state[cnt].oper = 1;
			state[cnt].pot1 = a;
			state[cnt].pot2 = state[cur].pot2;
			state[cnt].step = state[cur].step + 1;
			vis[state[cnt].pot1][state[cnt].pot2] = 1;
			Q.push(cnt);
		}
		if ( ! vis[state[cur].pot1][b] ) /* 将2装满 */
		{
			cnt++;
			father[cnt] = cur;
			state[cnt].oper = 2;
			state[cnt].pot1 = state[cur].pot1;
			state[cnt].pot2 = b;
			state[cnt].step = state[cur].step + 1;
			vis[state[cnt].pot1][state[cnt].pot2] = 1;
			Q.push(cnt);
		}
		if ( ! vis[0][state[cur].pot2] ) /* 将1清空 */
		{
			cnt++;
			father[cnt] = cur;
			state[cnt].oper = 3;
			state[cnt].pot1 = 0;
			state[cnt].pot2 = state[cur].pot2;
			state[cnt].step = state[cur].step + 1;
			vis[state[cnt].pot1][state[cnt].pot2] = 1;
			Q.push(cnt);
		}
		if ( ! vis[state[cur].pot1][0] ) /* 将2清空 */
		{
			cnt++;
			father[cnt] = cur;
			state[cnt].oper = 4;
			state[cnt].pot1 = state[cur].pot1;
			state[cnt].pot2 = 0;
			state[cnt].step = state[cur].step + 1;
			vis[state[cnt].pot1][state[cnt].pot2] = 1;
			Q.push(cnt);
		}
		temp = state[cur].pot1 > b-state[cur].pot2 ? b-state[cur].pot2 : state[cur].pot1;
		if ( ! vis[state[cur].pot1-temp][state[cur].pot2+temp] ) /* 将 1 倒入 2 */
		{
			cnt++;
			father[cnt] = cur;
			state[cnt].oper = 5;
			state[cnt].pot1 = state[cur].pot1 - temp;
			state[cnt].pot2 = state[cur].pot2 + temp;
			state[cnt].step = state[cur].step + 1;
			vis[state[cnt].pot1][state[cnt].pot2] = 1;
			Q.push(cnt);
		} 
		temp = state[cur].pot2 > a-state[cur].pot1 ? a-state[cur].pot1 : state[cur].pot2;
		if ( ! vis[state[cur].pot1+temp][state[cur].pot2-temp] ) /* 将2倒入1 */
		{
			cnt++;
			father[cnt] = cur;
			state[cnt].oper = 6;
			state[cnt].pot1 = state[cur].pot1+temp;
			state[cnt].pot2 = state[cur].pot2-temp;
			state[cnt].step = state[cur].step + 1;
			vis[state[cnt].pot1][state[cnt].pot2] = 1;
			Q.push(cnt);
		}
	}
	return -1;
}

int main()
{
	scanf("%d%d%d",&a,&b,&c);
	memset(vis,0,sizeof(vis));
	memset(state,0,sizeof(state));
	int temp = bfs();
	if ( temp == -1 )
		printf("impossible\n");
	else if ( temp == 0 )
		printf("%d\n",temp);
	else
	{
		printf("%d\n",state[temp].step);
		print(temp);
	}
	return 0;
}


评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值