UVa10603

隐式图的遍历

采用广度优先搜索的算法,从当前节点front扩展出所有可能的节点。扩展就是从一个杯子的水往另外一个杯子里面倒。

首先需要判断一下可以倒多少水,从第i个杯子往第j个杯子里面倒,如果第i个杯子有L升,第j个杯子有K升,则第j个杯子还能容纳cap[j]-K升,cap为容量。

倒完后用vis数组判重。只需要开两个状态即可,即第一个和第二个杯子的倒水量,重了就不扩展,不重的话就入队进行扩展。

AC代码:

#include<iostream>
#include<cstring>
using namespace std;
#define Max 201
struct Node{
	int volume[3];
	int amount;
};
int cap[3],flag;
int d,front,rear;
int vis[Max][Max];
Node q[Max*Max];
void bfs(void){
	int i,j,amount,k;
	q[0].volume[0]=q[0].volume[1]=q[0].amount=0;
	q[0].volume[2]=cap[2];
	vis[0][0]=1;
	front=0,rear=1;
	while(front<rear){
		Node &now=q[front];
		if(now.volume[0]==d||now.volume[1]==d||now.volume[2]==d){
			flag=1;
			return ;
		}
		for(i=0;i<3;i++){
			for(j=0;j<3;j++){
				if(i!=j){
					Node &next=q[rear];
					amount=now.volume[i]<(cap[j]-now.volume[j])?now.volume[i]:cap[j]-now.volume[j];
					for(k=0;k<3;k++)
						next.volume[k]=now.volume[k];
					next.volume[i]-=amount;
					next.volume[j]+=amount;
					if(!vis[next.volume[1]][next.volume[2]]){
						vis[next.volume[1]][next.volume[2]]=1;
						next.amount=now.amount+amount;
						rear++;
					}
				}
			}
		}
		front++;
	}
}
int main()
{
	int i,j,test_case;
	cin >>test_case;
	while(test_case--){
		flag=0;
		memset(vis,0,sizeof(vis));
		for(i=0;i<3;i++)
			cin>>cap[i];
    	cin>>d;
    	bfs();
    	if(flag==1){
			cout << q[front].amount << " " << d << endl;
    	}
		else{
			for(i=d-1;i>=0;i--){
				for(j=0;j<=rear;j++){
					if(q[j].volume[0]==i||q[j].volume[1]==i||q[j].volume[2]==i){
						flag=1;
						break;
					}
				}
				if(flag)
					break;
			}
			cout << q[j].amount <<" " <<i<<endl;
		}
	}
	return 0;
}

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值