poj 3414

独立做出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;
}


阅读更多
个人分类: 搜索
想对作者说点什么? 我来说一句

没有更多推荐了,返回首页

关闭
关闭
关闭