• UVA10603Fill题解--BFS


    题目链接

    https://cn.vjudge.net/problem/UVA-10603

    分析

    经典的倒水问题,直接BFS.

    对于喜闻乐见的状态判重,一开始想来个哈希函数把一个三元组映射成一个数,后面发现数据很小直接三维数组,后面又发现总水量是固定值,直接二维(bool)数组就好了

    然后每次取出状态更新下答案,搜索时就是枚举将哪个杯子的水倒入哪个杯子还是很好写的,记得要状态还原

    忽然发现最近只会写写水题过活了

    代码

    #include <cstdio>
    #include <cstring>
    #include <cstdlib>
    #include <algorithm>
    #include <cctype>
    #include <queue>
    #define ll long long 
    #define ri register int 
    #define ull unsigned long long 
    using std::priority_queue;
    using std::min;
    using std::swap;
    template <class T>inline void read(T &x){
    	x=0;int ne=0;char c;
    	while(!isdigit(c=getchar()))ne=c=='-';
    	x=c-48;
    	while(isdigit(c=getchar()))x=(x<<3)+(x<<1)+c-48;
    	x=ne?-x:x;return ;
    }
    const int maxn=205;
    const int inf=0x7fffffff;
    int ans=inf,step=0;
    int a,b,c,d;
    struct Sta{
    	int bot[3];
    	int sum;
    	Sta(){bot[0]=bot[1]=bot[2]=sum=0;}
    	Sta(int _x,int _y,int _z,int _sum){bot[0]=_x,bot[1]=_y,bot[2]=_z,sum=_sum;}
    	inline bool update(){
    		for(ri i=0;i<3;i++){
    			if(bot[i]>d)continue;
    			if(ans>d-bot[i]){
    				ans=d-bot[i];
    				step=sum;
    			}
    		}
    		if(!ans)return 1;
    		return 0;
    	}
    	bool operator <(const Sta &b)const{
    		return sum>b.sum;
    	}
    }Tmp;
    bool vis[205][205];
    int size[3],now[3];
    int t;
    inline void bfs(){
    	memset(vis,0,sizeof(vis));
    	ans=inf,step=0;
    	priority_queue <Sta> q;
    	while(q.size())q.pop();
    	q.push(Sta(0,0,c,0));
    	vis[0][0]=1;
    	int x,y,z,lef,o,p;
    	while(q.size()){
    		Tmp=q.top();q.pop();
    		if(Tmp.update()){
    			printf("%d %d
    ",Tmp.sum,d-ans);
    			return ;
    		}
    		now[0]=Tmp.bot[0],now[1]=Tmp.bot[1],now[2]=Tmp.bot[2],o=Tmp.sum;
    		for(ri i=0;i<3;i++){//i倒入j杯 
    			for(ri j=0;j<3;j++){
    				if(!now[i]||size[j]==now[j]||i==j)continue;
    				lef=size[j]-now[j];
    				if(now[i]>=lef){
    					now[i]-=lef;
    					now[j]=size[j];
    					if(!vis[now[0]][now[1]]){
    						vis[now[0]][now[1]]=1;
    						q.push(Sta(now[0],now[1],now[2],o+lef));
    					}
    					now[i]+=lef;
    					now[j]-=lef;
    				}
    				else{
    					p=now[i];
    					now[i]=0;
    					now[j]+=p;
    					if(!vis[now[0]][now[1]]){
    						vis[now[0]][now[1]]=1;
    						q.push(Sta(now[0],now[1],now[2],o+p));
    					}
    					now[i]=p;
    					now[j]-=p;
    				}
    			}
    		}
    	}
    	printf("%d %d
    ",step,d-ans);
    	return ;
    }
    int main(){
    	read(t);
    	while(t--){	
    		read(a),read(b),read(c),read(d);
    		size[0]=a,size[1]=b,size[2]=c;
    		bfs();
    	}
    	return 0;
    }
    
  • 相关阅读:
    final修饰符
    数组知识点
    session的作用范围(转)
    c++之list学习
    C++之重载操作符
    C++之浅拷贝构造函数与深拷贝构造函数
    C++之友元
    C++之共有继承、保护继承、私有继承
    C++之类静态成员变量和静态成员函数
    C源程序到可执行文件的四个过程
  • 原文地址:https://www.cnblogs.com/Rye-Catcher/p/9545298.html
Copyright © 2020-2023  润新知