poj 3414

原创 2018年04月17日 20:14:46

独立做出1道题所带来的快感要大于看题解做100道题。

老虎吞天,无从下口。但是蚕吃桑叶,却可以吃得叶子连渣都不剩。

解决这道题让我这么高兴是因为我补上了自己acm路上的一个缺陷——如何用一种普适性的办法恢复bfs的路径。

   众所周知,dfs和bfs在搜索的过程中会生成一颗深(广)度优先搜索树,由于bfs一旦找到一个解,这个解就是最优解,那么相应地它也失去了dfs的一个特性——dfs的路径可以通过覆盖的方法简单高效求得。那么,bfs的路径该如何还原?

曾经,我是通过记录从起点到各个状态的距离,然后再从终点回溯求得,依据是若点x的距离为t,那么与x相邻的有且仅有一个点的距离为t-1.

现在这个思路是来源于树,把每个状态看做一个结点,结点存储以下信息:结点的状态,结点的编号,该结点的前驱结点的编号,以及到达该节点进行了什么操作。具体有什么视题目而定,这儿的关键是前驱结点的编号。还有一点,因为是搞竞赛,效率为主,所以没有使用出错率较高的指针,而是直接开辟数组。


再说一下这道题还可以改进的地方吧,就像非常可乐一样,总感觉状态的转移可以靠循环实现,研究出来后补上它。

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

struct data{
	int a, b, c;
};
struct vertice{
	int num;
	int x, y;
	int pre;
	data oper;
};
bool vis[110][110];
int cnt = 1;
int A, B, C;
int ac = 0;
vertice node[1000000];

void bfs(vertice s){
	queue <vertice> q;
	vis[s. x][s. y] = true;
	q. push(s);
	while(! q. empty()){
		vertice t = q. front();
		q. pop();
		
		if(t. x == C || t. y == C){
			ac = t. num;
			break;
		}
		
		int nx, ny;		
		nx = A, ny = t. y;
		if(vis[nx][ny] == false){
			vis[nx][ny] = true;
			node[cnt]. num = cnt;
			node[cnt]. x = nx, node[cnt]. y = ny;
			node[cnt]. pre = t. num;
			node[cnt]. oper = {1, 1, 1};
			q. push(node[cnt]);
			cnt ++;
		}
		nx = t. x, ny = B;
		if(vis[nx][ny] == false){
			vis[nx][ny] = true;
			node[cnt]. num = cnt;
			node[cnt]. x = nx, node[cnt]. y = ny;
			node[cnt]. pre = t. num;
			node[cnt]. oper = {1, 2, 1};
			q. push(node[cnt]);
			cnt ++;
		}
		
		nx = 0, ny = t. y;
		if(vis[nx][ny] == false){
			vis[nx][ny] = true;
			node[cnt]. num = cnt;
			node[cnt]. x = nx, node[cnt]. y = ny;
			node[cnt]. pre = t. num;
			node[cnt]. oper = {2, 1, 1};
			q. push(node[cnt]);
			cnt ++;
		}
		nx = t. x, ny = 0;
		if(vis[nx][ny] == false){
			vis[nx][ny] = true;
			node[cnt]. num = cnt;
			node[cnt]. x = nx, node[cnt]. y = ny;
			node[cnt]. pre = t. num;
			node[cnt]. oper = {2, 2, 1};
			q. push(node[cnt]);
			cnt ++;
		}
		
		int x;		
		x = min(t. x, B - t. y);
		nx = t. x - x, ny = t. y + x;
		if(vis[nx][ny] == false){
			vis[nx][ny] = true;
			node[cnt]. num = cnt;
			node[cnt]. x = nx, node[cnt]. y = ny;
			node[cnt]. pre = t. num;
			node[cnt]. oper = {3, 1, 2};
			q. push(node[cnt]);
			cnt ++;
		}
		x = min(A - t. x, t. y);
		nx = t. x + x, ny = t. y - x;
		if(vis[nx][ny] == false){
			vis[nx][ny] = true;
			node[cnt]. num = cnt;
			node[cnt]. x = nx, node[cnt]. y = ny;
			node[cnt]. pre = t. num;
			node[cnt]. oper = {3, 2, 1};
			q. push(node[cnt]);
			cnt ++;
		}		
	}
}

void print(){
	vector <data> ans;
	int i = ac;
	while(node[i]. pre != -1){
		ans. push_back(node[i]. oper);
		i = node[i]. pre;
	}
	if(ans. size() == 0){
		cout << "impossible" << endl;
		return ;
	}
	cout << ans. size() << endl;
	for(int i = ans. size() - 1; i >= 0; i --){
		if(ans[i]. a == 1){
			printf("FILL(%d)\n", ans[i]. b);
		}
		if(ans[i]. a == 2){
			printf("DROP(%d)\n", ans[i]. b);
		}
		if(ans[i]. a == 3){
			printf("POUR(%d,%d)\n", ans[i]. b, ans[i]. c);
		}
	}
}

int main(){
	cin >> A >> B >> C;
	node[0]. num = 0;
	node[0]. x = 0;
	node[0]. y = 0;
	node[0]. pre = -1;
	bfs(node[0]);
	print();
	return 0;
}


poj 3414解题报告

  • 2010年04月02日 13:23
  • 8KB
  • 下载

POJ 3414-Pots(BFS-模拟倒水)

Pots Time Limit: 1000MS   Memory Limit: 65536K Total Submissions: 15785   Accepted...
  • MIKASA3
  • MIKASA3
  • 2017-02-24 14:35:34
  • 283

poj 3414 Pots(广搜BFS+路径输出)

poj3414 Pots(BFS+路径输出)
  • u012860063
  • u012860063
  • 2014-07-14 20:18:04
  • 2332

POJ 3414-Pots(BFS)

题目地址:POJ 3414 题意:给你a,b两个容器的容量,六种操作方法,问最少多少次可以使其中一个容器里的水达到体积c,如果不能的话则输出impossible。 思路:一共有6种操作方法,0:倒...
  • u013486414
  • u013486414
  • 2015-08-16 18:29:07
  • 750

Pots (POJ - 3414 )(BFS)

BFS
  • Coldfresh
  • Coldfresh
  • 2017-04-19 00:44:37
  • 151

POJ3414 Pots【倒水问题+BFS】

Pots Time Limit: 1000MS   Memory Limit: 65536K Total Submissions: 19641   Accepted...
  • tigerisland45
  • tigerisland45
  • 2016-08-15 09:23:57
  • 768

Pots(POJ_3414)

DescriptionYou are given two pots, having the volume of A and B liters respectively. The following o...
  • highmath_Final
  • highmath_Final
  • 2015-08-21 11:16:22
  • 466

POJ3414---Pots

#include #include #include #include #include #include using namespace std; #define MAXN 110 char str...
  • hy1405430407
  • hy1405430407
  • 2015-06-13 11:29:17
  • 318

3414POJ

给你两个杯子,问你怎么操作可以将这两个杯子其中一个杯子的容量达到目标状态,一共有三个操作 1,把杯子装满。 2,把杯子倒空。 3,一个杯子的水倒向另一杯子。 BFS。。 注意是一次输入一次输...
  • wang57389675
  • wang57389675
  • 2015-08-08 14:29:05
  • 292

poj 3414 Pots 广度优先搜索

Description You are given two pots, having the volume of A and B liters respectively. The followi...
  • u013087645
  • u013087645
  • 2014-07-30 00:53:29
  • 721
收藏助手
不良信息举报
您举报文章:poj 3414
举报原因:
原因补充:

(最多只允许输入30个字)