poj3414 - Pots

题目链接:点击打开链接


题意:

有两个壶,分别有A, B升水,问通过三个操作FILL, DROP, POUR,是否能使得这两个壶中有一个壶刚好有C升水。输出最少的操作步数,以及每一步具体的操作。


思路:

bfs,得到最少步数。因为要输出具体步骤,在bfs过程中要记录之前的操作,设置pre指针,指向之前的节点,路径的记录直接用了STL的stack...

在bfs中,我把每一步操作细分,然后用了函数指针数组,方便bfs。

然后dfs,输出路径。


wa了两发,发现忘记输出impossible了。


代码:

#include <iostream>
#include <cstdio>
#include <cstring>
#include <queue>
#include <stack>

using namespace std;

int a, b, c;

const char str[6][10] = {
	"FILL(1)",
	"FILL(2)",
	"POUR(1,2)",
	"POUR(2,1)",
	"DROP(1)",
	"DROP(2)"
};

struct Node
{
	int a, b;
	int order, cnt;
	Node *pre;
	Node(int a, int b, int order, int cnt, Node*pre){
        this->a = a; this->b = b; this->order = order;
        this->cnt = cnt; this->pre = pre;
	}
};

void fill1(Node &tmp){
	tmp.a = a;
}

void fill2(Node &tmp){
	tmp.b = b;
}

void pour1to2(Node &tmp){
	int cha = b - tmp.b;
	if(cha < tmp.a){
		tmp.b = b;
		tmp.a -= cha;
	}
	else{
		tmp.b += tmp.a;
		tmp.a = 0;
	}
}

void pour2to1(Node &tmp){
	int cha = a - tmp.a;
	if(cha < tmp.b){
		tmp.a = a;
		tmp.b -= cha;
	}
	else{
		tmp.a += tmp.b;
		tmp.b = 0;
	}
}

void drop1(Node &tmp){
	tmp.a = 0;
}

void drop2(Node &tmp){
	tmp.b = 0;
}

void (*menu[])(Node &tmp) = {fill1, fill2, pour1to2, pour2to1, drop1, drop2};

const int MAXN = 100 + 10;
bool vis[MAXN][MAXN];

void dfs(Node* temp){
	if(temp->order==-1 || temp->pre==NULL) return;
	dfs(temp->pre);
	printf("%s\n", str[temp->order]);
}

void bfs(){
	queue<Node> q;
	stack<Node> ans;
	q.push(Node(0, 0, -1, 0, NULL));  //a, b, order, cnt, pre;
	memset(vis, 0, sizeof(vis));
	while(!q.empty()){
		ans.push(q.front()); q.pop();
		Node temp = ans.top();
		if(temp.a==c || temp.b==c){
			printf("%d\n", temp.cnt);
			dfs(&temp);
			return;
		}
		for(int i=0; i<6; ++i){
			Node another = temp;
			menu[i](another);
			if(vis[another.a][another.b]) continue;
			another.pre = &ans.top();
			another.order = i;
			++another.cnt;
			q.push(another);
			vis[another.a][another.b] = true;
		}
	}
	printf("impossible\n");
}

int main(){
	scanf("%d%d%d", &a, &b, &c);
	bfs();
	return 0;
}


评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值