poj3414 openjudge3151 pots解题报告

总时间限制: 
1000ms 
内存限制: 
65536kB
描述

You are given two pots, having the volume of A and B liters respectively. The following operations can be performed:

  1. FILL(i)        fill the pot i (1 ≤ ≤ 2) from the tap;
  2. DROP(i)      empty the pot i to the drain;
  3. POUR(i,j)    pour from pot i to pot j; after this operation either the pot j is full (and there may be some water left in the pot i), or the pot i is empty (and all its contents have been moved to the pot j).

Write a program to find the shortest possible sequence of these operations that will yield exactly C liters of water in one of the pots.

输入

On the first and only line are the numbers AB, and C. These are all integers in the range from 1 to 100 and C≤max(A,B).

输出

The first line of the output must contain the length of the sequence of operations K. The following K lines must each describe one operation. If there are several sequences of minimal length, output any one of them. If the desired result can’t be achieved, the first and only line of the file must contain the word ‘impossible’.

样例输入
3 5 4

样例输出

6
FILL(2)
POUR(2,1)
DROP(1)
POUR(2,1)
FILL(2)
POUR(2,1)
分析:

这道题目就是一道很普通的广搜题目,但是因为它里面涉及到了很多的选择,也涉及到了回溯,所以对于基本功和基本的广搜算法的联系很有意义,对于新手来说是很宝贵的锻炼机会。

思路很简单,对于每个状态用一个status的结构存储,记录下来两个水壶里的水量、现在是第几步、达到这个状态的上一步操作(我们可以用一个整数operation来存储)和这个状态的前一个状态在数组的什么位置(用来回溯)。

上代码:

#include<iostream>
#include<cstring>
#include<algorithm>
using namespace std;
struct status
{
	int pot1;
	int pot2;
	int opration;//0,1 fill;2,3 pour;4,5 drop
	int steps;
	int signal;
	status(int a, int b, int c) :pot1(a), pot2(b), steps(c) {}
	status() {}
};
status open[40000];
bool walked[110][110];
void Print(int x) {    //针对对应的operation打印
	if (x == 0)
		cout << "FILL(1)" << endl;
	else if (x == 1)
		cout << "FILL(2)" << endl;
	else if (x == 2)
		cout << "POUR(1,2)" << endl;
	else if (x == 3)
		cout << "POUR(2,1)" << endl;
	else if (x == 4)
		cout << "DROP(1)" << endl;
	else
		cout << "DROP(2)" << endl;
	return;
}
int main()
{
	int x1, x2, y;
	cin >> x1 >> x2 >> y;
	status tmp(0, 0, 0); open[0] = tmp;
	status *head, *tail;
	head = open; tail = open + 1;
	head->signal = 0;
	walked[0][0] = true;
	int flag = 0;
	while (head != tail) {
		tmp = *head;
		if (tmp.pot1 == y || tmp.pot2 == y) {
			flag = 1;
			break;
		}
		for (int ope = 0; ope < 6; ope++) {
			switch (ope) {
			case 0:
				if (tmp.pot1 != x1 && !walked[x1][tmp.pot2]) {
					*tail = status(x1, tmp.pot2, tmp.steps + 1);
					walked[x1][tmp.pot2] = true;
					tail->opration = 0;
					tail->signal = head - open;
					tail++;
				}
				break;
			case 1:
				if (tmp.pot2 != x2 && !walked[tmp.pot1][x2]) {
					*tail = status(tmp.pot1, x2, tmp.steps + 1);
					tail->opration = 1;
					walked[tmp.pot1][x2] = true;
					tail->signal = head - open;
					tail++;
				}
				break;
			case 2:
				if (tmp.pot1 != 0 && tmp.pot2 < x2) {
					if (tmp.pot1 >= (x2 - tmp.pot2) && !walked[tmp.pot1 + tmp.pot2 - x2][x2]) {
						*tail = status(tmp.pot1 + tmp.pot2 - x2, x2, tmp.steps + 1);
						tail->opration = 2;
						walked[tail->pot1][tail->pot2] = true;
						tail->signal = head - open;
						tail++;
					}
					else if (tmp.pot1 + tmp.pot2 <= x2 && !walked[0][tmp.pot1 + tmp.pot2]) {
						*tail = status(0, tmp.pot1 + tmp.pot2, tmp.steps + 1);
						tail->opration = 2;
						walked[tail->pot1][tail->pot2] = true;
						tail->signal = head - open;
						tail++;
					}
				}
				break;
			case 3:
				if (tmp.pot2 != 0 && tmp.pot1 < x1) {
					if (tmp.pot2 >= (x1 - tmp.pot1) && !walked[x1][tmp.pot1 + tmp.pot2 - x1]) {
						*tail = status(x1, tmp.pot1 + tmp.pot2 - x1, tmp.steps + 1);
						tail->opration = 3;
						walked[tail->pot1][tail->pot2] = true;
						tail->signal = head - open;
						tail++;
					}
					else if (tmp.pot1 + tmp.pot2 <= x1 && !walked[tmp.pot1 + tmp.pot2][0]) {
						*tail = status(tmp.pot1 + tmp.pot2, 0, tmp.steps + 1);
						tail->opration = 3;
						walked[tail->pot1][tail->pot2] = true;
						tail->signal = head - open;
						tail++;
					}
				}
				break;
			case 4:
				if (tmp.pot1 != 0 && !walked[0][tmp.pot2]) {
					*tail = status(0, tmp.pot2, tmp.steps + 1);
					tail->opration = 4;
					walked[tail->pot1][tail->pot2] = true;
					tail->signal = head - open;
					tail++;
				}
				break;
			case 5:
				if (tmp.pot2 != 0 && !walked[tmp.pot1][0]) {
					*tail = status(tmp.pot1, 0, tmp.steps + 1);
					tail->opration = 5;
					walked[tail->pot1][tail->pot2] = true;
					tail->signal = head - open;
					tail++;
				}
				break;
			}
		}
		head++;
	}
	if (flag == 0)
		cout << "impossible" << endl;
	else {
		int t = head->steps;
		cout << t << endl;
		int *sol = new int[t];
		int temp = head - open;
		for (int i = t - 1; i >= 0; i--) {
			sol[i] = open[temp].opration;
			if (i != 0)
				temp = open[temp].signal;
		}
		for (int i = 0; i < t; i++)
			Print(sol[i]);
	}
	return 0;
}

恍恍惚惚就写了140多行,应该还有优化的空间,但是最近期末了,优化的工作就先交给读者了!

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值