2021-08-04

poj3414题解与思考 Pots

  1. 题意
  2. 知识点
  3. 题解:
    首先第一次拿到这个题,觉得麻烦,想第一时间把答案中步数输出来,再去想怎么输出具体每一步怎么操作,于是就有了如下代码,(自己想的),用到bfs和队列)
#include<iostream>
#include<queue>
using namespace std;

struct set {
	int a;
	int b;
	int step;
};
int  amax, bmax, c;
bool vis[500][500];

void find() {
	set x;
	x.a = 0;
	x.b = 0;
	x.step = 0;
	queue<set> q;
	q.push(x);
	vis[x.a][x.b] = true;
	while (!q.empty()) {
		set z;
		set y = q.front();
		q.pop();
		if (y.a == c || y.b == c) {
			cout << y.step << endl;
			return;
		}
		for (int i = 0; i < 6; i++) {
			//FILL(1)
			if (i == 0) {
				z.a = amax;
				z.b = y.b;
				if (!vis[z.a][z.b]) {
					z.step = y.step + 1;
					q.push(z);
					vis[z.a][z.b] = true;
				}
			}
			//FILL(2)
			if (i == 1) {
				z.a = y.a;
				z.b = bmax;
				if (!vis[z.a][z.b]) {
					z.step = y.step + 1;
					q.push(z);
					vis[z.a][z.b] = true;
				}
			}
			//DROP(1)
			if (i == 2) {
				z.a = 0;
				z.b = y.b;
				if (!vis[z.a][z.b]) {
					z.step = y.step + 1;
					q.push(z);
					vis[z.a][z.b] = true;
				}
			}
			//DROP(2)
			if (i == 3) {
				z.a = y.a;
				z.b = 0;
				if (!vis[z.a][z.b]) {
					z.step = y.step + 1;
					q.push(z);
					vis[z.a][z.b] = true;
				}
			}
			//POUR(1,2)
			if (i == 4) {
				if (y.a + y.b <= bmax) {
					z.a = 0;
					z.b = y.a + y.b;
					if (!vis[z.a][z.b]) {
						z.step = y.step + 1;
						q.push(z);
						vis[z.a][z.b] = true;
					}
				}
				else if (y.a + y.b > bmax) {
					z.a = (y.a + y.b) - bmax;
					z.b = bmax;
					if (!vis[z.a][z.b]) {
						z.step = y.step + 1;
						q.push(z);
						vis[z.a][z.b] = true;
					}
				}
			}
			//POUR(2,1)
			if (i == 5) {
				if (y.a + y.b <= amax) {
					z.a = y.a + y.b;
					z.b =0;
					if (!vis[z.a][z.b]) {
						z.step = y.step + 1;
						q.push(z);
						vis[z.a][z.b] = true;
					}
				}
				else if (y.a + y.b > amax) {
					z.a =  amax;
					z.b = (y.a + y.b) - amax;
					if (!vis[z.a][z.b]) {
						z.step = y.step + 1;
						q.push(z);
						vis[z.a][z.b] = true;
					}
				}
			}
		}
	}
}

int main() {
	while (cin >> amax >> bmax >> c) {
		memset(vis, false, sizeof(vis));
		find();
	}
	return 0;
}

再进一步想想怎么输出每一步呐,用bfs搜索的,最后输出需要回溯,而bfs的回溯实现我暂时没有好的思路。苦思冥想,终于我想到了一个可实现的方法。

首先我们能想到,可以把for循环里的具体操作添加给结构体,添加一个string s即可(因为for循环里的操作是有具体数字对应的,例如FULL(1)对应i=0)
其次我们观察到find函数里有z.step = y.step + 1这就说明,其实每一步的操作是与前一步有联系的,如果我们能将之前的操作与当前的操作一同赋给结构体z,最后输出z.s时就输出了得到z的操作和之前的所有操作!
最后,由于“for循环里的操作是有具体数字对应的”我们完全可以只将数字添加给结构体,最后输出时根据数字输出对应的操作就好了!(用到switch语句)
代码奉上:

//AC! 相信自己,尊重题意!
#include<iostream>
#include<queue>
#include<string>
#include<cstring>
using namespace std;

struct set {
	int a;
	int b;
	int step;
	string s;
};
int  amax, bmax, c;
bool vis[500][500];

void find() {
	set x;
	x.a = 0;
	x.b = 0;
	x.step = 0;
	int head, tail;
	//x.pos = head;
	head  = 0;
	tail = 1;
	queue<set> q;
	//set queue[1000];
	//queue[head] = x;
	q.push(x);
	vis[x.a][x.b] = true;
	while (!q.empty()) {
		set z;
		set y = q.front();
		if (y.a == c || y.b == c) {
			cout << y.step << endl;
			for (int i = 0; i < y.s.length(); i++) {
				switch (y.s[i]) {
				case '1':
					cout << "FILL(1)" << endl;
					break;
				case '2':
					cout << "FILL(2)" << endl;
					break;
				case '3':
					cout << "DROP(1)" << endl;
					break;
				case '4':
					cout << "DROP(2)" << endl;
					break;
				case '5':
					cout << "POUR(1,2)" << endl;
					break;
				case '6':
					cout << "POUR(2,1)" << endl;
					break;
				}
			}
			return;
		}
		for (int i = 0; i < 6; i++) {
			//FILL(1)
			if (i == 0) {
				z.a = amax;
				z.b = y.b;
				if (!vis[z.a][z.b]) {
					z.step = y.step + 1;
					z.s = y.s + '1';
					q.push(z);
					vis[z.a][z.b] = true;
				}
			}
			//FILL(2)
			if (i == 1) {
				z.a = y.a;
				z.b = bmax;
				if (!vis[z.a][z.b]) {
					z.step = y.step + 1;
					z.s = y.s + '2';
					q.push(z);
					vis[z.a][z.b] = true;
				}
			}
			//DROP(1)
			if (i == 2) {
				z.a = 0;
				z.b = y.b;
				if (!vis[z.a][z.b]) {
					z.step = y.step + 1;
					z.s = y.s + '3';
					q.push(z);
					vis[z.a][z.b] = true;
				}
			}
			//DROP(2)
			if (i == 3) {
				z.a = y.a;
				z.b = 0;
				if (!vis[z.a][z.b]) {
					z.step = y.step + 1;
					z.s = y.s + '4';
					q.push(z);
					vis[z.a][z.b] = true;
				}
			}
			//POUR(1,2)
			if (i == 4) {
				if (y.a + y.b <= bmax) {
					z.a = 0;
					z.b = y.a + y.b;
					if (!vis[z.a][z.b]) {
						z.step = y.step + 1;
						z.s = y.s + '5';
						q.push(z);
						vis[z.a][z.b] = true;
					}
				}
				else if (y.a + y.b > bmax) {
					z.a = (y.a + y.b) - bmax;
					z.b = bmax;
					if (!vis[z.a][z.b]) {
						z.step = y.step + 1;
						z.s = y.s + '5';
						q.push(z);
						vis[z.a][z.b] = true;
					}
				}
			}
			//POUR(2,1)
			if (i == 5) {
				if (y.a + y.b <= amax) {
					z.a = y.a + y.b;
					z.b =0;
					if (!vis[z.a][z.b]) {
						z.step = y.step + 1;
						z.s = y.s + '6';
						q.push(z);
						vis[z.a][z.b] = true;
					}
				}
				else if (y.a + y.b > amax) {
					z.a =  amax;
					z.b = (y.a + y.b) - amax;
					if (!vis[z.a][z.b]) {
						z.step = y.step + 1;
						z.s = y.s + '6';
						q.push(z);
						vis[z.a][z.b] = true;
					}
				}
			}
		}
		q.pop();
	}
	cout << "impossible" << endl;
}

int main() {
	while (cin >> amax >> bmax >> c) {
		memset(vis, false, sizeof(vis));
		find();
	}
	return 0;
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值