kuangbin搜索专题 H - Pots

  • 时间:
  • 来源:互联网
  • 文章标签:

Pots

题目大意:(文末有原题)

给你两个空杯子的容积,问能否通过倒水使得其中一个杯子内水的体积变为n;如果可以,输出需要的最短步数和每一步的操作;

倒水:1. FILL(i) : 将第i个杯子注满水;(1<=i, j <= 2 && i != j)

            2. DROP(i) : 将第i个杯子的水倒掉;

            3. POUR(i, j) : 将第i个杯子内的水倒向第j个杯子,倒的结果:一个满,另一个空 或 一个满,另一个有剩余

思路:

因为只有两个杯子六种操作,容易列出,所以将每个操作写入数组,数字化表示出来;这样,只需多定义一个变量来记录代表每一步操作的数字,就可以确定每一步的操作;因为是要求最短步数,又是需要一层一层的来访问,所以用bfs,相对于基本的bfs,所多的是对每一步操作的储存与输出。

代码:

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

//仍然是将每个操作都数字化,当i是固定值时,操作就固定。
//但是需要输出每一步的操作,所以用另外一个数组来保存每一步的状态和操作情况,操作情况由确定的数字来确定 

const int maxn = 110;
int A, B, C;
char a[10][10] = {"FILL(1)", "FILL(2)", "DROP(1)", "DROP(2)", "POUR(1,2)", "POUR(2,1)"};
		//只有6种操作情况,通过数字来确定是哪种操作;
		 
struct Node{		
	int fromx, fromy, step, op;		//x,y确定上一步的状态,step 记录 步数,op 记录 操作情况; 
}v[maxn][maxn];			

struct point{
	int x, y;		//x,y表示两个杯子 
};

void DFS(int x, int y) {		//输出 
	if(x == 0 && y == 0) {
		return;	
	}
	
	DFS(v[x][y].fromx, v[x][y].fromy);
	printf("%s\n", a[v[x][y].op]);		//用op来确定是哪种操作,每个数对应二维数组中的字符串; 
}

void BFS() {
	queue<point> Q;		//队列中只对x,y来操作,但是用Node保存情况 
	point s, q;
	s.x = s.y = 0;			//初始状态是 两个空杯子 0,0 
	v[0][0].step = 0;
	Q.push(s);
	
	while(Q.size()) {		//等效 !Q.empty();  
		s = Q.front();
		Q.pop();
		
		if(s.x == C || s.y == C) {		//判断是否是所要求状态 
			cout << v[s.x][s.y].step << endl;
			DFS(s.x, s.y);		 
			return;
		}
		
		for(int i = 0; i < 6; i++) {		
			q = s;
			if(i == 0){
				q.x = A;
			}else if(i == 1){
				q.y = B;
			}else if(i == 2) {
				q.x = 0;
			}else if(i == 3) {
				q.y = 0;
			}else if(i == 4) {
				if(q.x + q.y <= B) {	//判断a能否够将b注满 
					q.y += q.x;
					q.x = 0;
				}else {					
					q.x -= (B - q.y);
					q.y = B;
				}
			}else{						 
				if(q.x + q.y <= A) {	
					q.x += q.y;
					q.y = 0;
				}else {
					q.y -= (A - q.x);
					q.x = A;
				}
			}
			
			if(v[q.x][q.y].step == 0) {		//v[][].step==0 对应 还没有到达过这个状态 
				v[q.x][q.y].step = v[s.x][s.y].step + 1;
				v[q.x][q.y].fromx = s.x;
				v[q.x][q.y].fromy = s.y;
				v[q.x][q.y].op = i;		 
				Q.push(q);
			}
		}
	}
	
	printf("impossible\n");
}

int main() {
	while(scanf("%d%d%d", &A, &B, &C) != EOF) {
		memset(v, 0, sizeof(v));
		BFS();
	}
	
	return 0;
}

原题:

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 ≤ i ≤ 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 A, B, 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’.

样例:

Input:

3 5 6

Output:

6

FILL(2)

POUR(2,1)

DROP(1)

POUR(2,1)

FILL(2)

POUR(2,1)

本文链接http://www.taodudu.cc/news/show-83148.html