您的位置:首页 > 其它

uva 10603倒水问题(搜索 隐式图的最短路 )

2015-05-12 17:20 357 查看
题意是:有三个没有刻度的水壶,容量分别为a,b和c(单位为升,都是<=200的正整数)。初始时前两个水壶是空的,而第三个装满了水。每次可以从一个水壶往一个水壶里倒水,直到一个水壶倒空或者另一个水壶倒满。为了让某个水壶恰好有d升水,至少要倒多少升的水?如果无解,找一个小于且最接近d的d’代替d。

这题照书敲得....敲完后想了想这题问的是倒水量,那么其实也可以用dfs,这样会简单些...

代码如下:

#include<cstdio>  
#include<cstring>  
#include<cmath>  
#include<cstdlib>  
#include<iostream>  
#include<algorithm>  
#include<vector>  
#include<map>  
#include<queue>  
#include<stack> 
#include<string>
#include<map> 
#include<set>
using namespace std;  
#define LL long long  
const int maxn=200+5;
//freopen("input.txt","r",stdin);

struct Node{
	int v[3],dist;
	bool operator< (const Node& rhs) const{
		return dist>rhs.dist;
	}
};

int vis[maxn][maxn],cap[3],ans[maxn];

void update_ans(const Node& u){
	for(int i=0;i<3;i++){
		int d=u.v[i];
		if(ans[d]<0||u.dist<ans[d]) ans[d]=u.dist;
	}
}

void solve(int a,int b,int c,int d){
	cap[0]=a;cap[1]=b;cap[2]=c;
	memset(vis,0,sizeof(vis));
	memset(ans,-1,sizeof(ans));
	priority_queue<Node> q;
	
	Node start;
	start.dist=0,start.v[0]=0,start.v[1]=0,start.v[2]=c;
	q.push(start);
	
	vis[0][0]=1;
	while(!q.empty()){
		Node u=q.top();q.pop();
		update_ans(u);
		if(ans[d]>=0) break;
		for(int i=0;i<3;i++)
			for(int j=0;j<3;j++) if(i!=j){//从i向j倒水 
				if(u.v[i]==0||u.v[j]==cap[j]) continue;
				int amount=min(cap[j],u.v[i]+u.v[j])-u.v[j];
				Node u2;
				memcpy(&u2,&u,sizeof(u));
				u2.dist+=amount;
				u2.v[i]-=amount;
				u2.v[j]+=amount;
				if(!vis[u2.v[0]][u2.v[1]]) {
					vis[u2.v[0]][u2.v[1]] = 1;
					q.push(u2);
				}
			}
			
	}
	while(d>=0){
		if(ans[d]>=0){
			printf("%d %d\n",ans[d],d);
			return;
		}
		d--;
	}
}

int main(){
	int T,a,b,c,d;
	scanf("%d",&T);
	while(T--){
		scanf("%d%d%d%d",&a,&b,&c,&d);
		solve(a,b,c,d);
	}
	return 0;
}



内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: