• 【解题报告】非常可乐(广度优先搜索入门题)


    题意:给你3个杯子,容量分别为S,N,M,其中S=N+M,三个数都是正整数.一开始S是满的,N和M都是空的,杯子都没刻度.最少倒几次能使其中两个杯子平分可乐.

    这道题是个BFS的入门题,解法很容易想到:

    • 杯子都没刻度,说明A杯往B杯倒可乐,只有2种情况:把B倒满,或者把A倒空,所以我们就可以得到2个新的状态,把它们加入广搜队列;当然A->B有6种排列方式,所以总共要写十二次倒可乐的状态转移操作.

    • 最少倒几次能使其中两个杯子平分可乐:也就是说第一次出现两个杯子的可乐量等于s/2时的操作次数.可以知道s % 2=1的话是肯定不可能有解的.

    在此,主要用这个题练练STL:如何用STL方便地帮助搜索

    注意:下面这种tuple、map的用法,在某些搜索的情景下是低效的,完全可以用struct和三维数组高效代替,此处只是练习STL

    1. 表示当前可乐容量状态的三元组:

    可以用含有三个元素的结构体存储状态,并且把它入队.STL里的tuple可以方便地存储一个多元组,这样就不用结构体啦:

    定义一个三元组:

    tuple<int,int,int>head;

    获取该状态下的三个元素:

    x=get<0>(head); y=get<1>(head); z=get<2>(head);

    给这个组添加元素,比如s,0,0:

    head=make_tuple(s,0,0);

    2. 当前可乐容量状态对应的已经进行的倾倒次数:

    自然而然想到map了

    map<tuple<int,int,int>,int>dist;

    3. 某一状态是否已经被访问(搜索)过:

    这个同上,其实完全可以用上面的dist代替:假如没被搜过,它对应的次数就是0啦

    4.把map和tuple初始化为空,用.clear()函数就可以了

    (tuple+map)AC代码
    #include<bits/stdc++.h>
    using namespace std;
    const int MAXN=100+5;
    const int MAXM=0+5;
    const int INF=0x3f3f3f3f;
    int s,n,m;
    queue<tuple<int,int,int> >q;
    map<tuple<int,int,int>,int>dist;
    tuple<int,int,int>tmp;
    tuple<int,int,int>head;
    bool daoman(int i,int j,int p) {
    	return (i>=p-j)?1:0;
    }
    bool daokong(int i,int j,int p) {
    	return (i+j<=p)?1:0;
    }
    void doit() {
    	q.push(tmp);
    	dist[tmp]=dist[head]+1;
    }
    void bfs() {
    	head=make_tuple(s,0,0);
    	q.push(head);
    	int mn=INF;
    	while(q.size()) {
    		head=q.front();
    		q.pop();
    		int x=get<0>(head),y=get<1>(head),z=get<2>(head);
    		if((x==s/2&&y==s/2)||(x==s/2&&z==s/2))mn=min(mn,dist[head]);
    		if(mn!=INF) {
    			cout<<mn<<'\n';
    			break;
    		}
    		if(daoman(x,y,n)) {
    			tmp=make_tuple(x-(n-y),n,z);
    			if(!dist[tmp]) doit();
    		}
    		if(daoman(x,z,m)) {
    			tmp=make_tuple(x-(m-z),y,m);
    			if(!dist[tmp]) doit();
    		}
    		if(daoman(y,z,m)) {
    			tmp=make_tuple(x,y-(m-z),m);
    			if(!dist[tmp]) doit();
    		}
    		if(daoman(y,x,s)) {
    			tmp=make_tuple(s,y-(s-x),z);
    			if(!dist[tmp])doit();
    		}
    		if(daoman(z,x,s)) {
    			tmp=make_tuple(s,y,z-(s-x));
    			if(!dist[tmp]) doit();
    		}
    		if(daoman(z,y,n)) {
    			tmp=make_tuple(x,n,z-(n-y));
    			if(!dist[tmp]) doit();
    		}
    		if(daokong(x,y,n)) {
    			tmp=make_tuple(0,x+y,z);
    			if(!dist[tmp]) doit();
    		}
    		if(daokong(x,z,m)) {
    			tmp=make_tuple(0,y,x+z);
    			if(!dist[tmp])doit();
    		}
    		if(daokong(y,z,m)) {
    			tmp=make_tuple(x,0,y+z);
    			if(!dist[tmp]) doit();
    		}
    		if(daokong(y,x,s)) {
    			tmp=make_tuple(x+y,0,z);
    			if(!dist[tmp]) doit();
    		}
    		if(daokong(z,x,s)) {
    			tmp=make_tuple(x+z,y,0);
    			if(!dist[tmp]) doit();
    		}
    		if(daokong(z,y,n)) {
    			tmp=make_tuple(x,y+z,0);
    			if(!dist[tmp]) doit();
    		}
    	}
    	if(mn==INF)cout<<"NO"<<'\n';
    }
    int main() {
    	ios::sync_with_stdio(false);
    	cin.tie(NULL);
    	while(cin>>s>>n>>m) {
    		if(!s&&!n&&!m)break;
    		while(q.size())q.pop();
    		dist.clear();
    		if(s%2)cout<<"NO"<<'\n';
    		else bfs();
    	}
    	return 0;
    }
    
    (结构体+三维数组)AC代码
    #include<bits/stdc++.h>
    using namespace std;
    const int MAXN=100+5;
    const int MAXM=0+5;
    const int INF=0x3f3f3f3f;
    int s,n,m;
    int x,y,z;
    int dist[MAXN][MAXN][MAXN];
    struct node {
    	int x,y,z;
    } head,tmp;
    queue<struct node>q;
    bool daoman(int i,int j,int p) {
    	return (i>=p-j)?1:0;
    }
    bool daokong(int i,int j,int p) {
    	return (i+j<=p)?1:0;
    }
    void doit(int xx,int yy,int zz) {
    	if(dist[xx][yy][zz])return;
    	tmp.x=xx,tmp.y=yy,tmp.z=zz;
    	q.push(tmp);
    	dist[xx][yy][zz]=dist[x][y][z]+1;
    }
    void bfs() {
    	head.x=s,head.y=0,head.z=0;
    	q.push(head);
    	int mn=INF;
    	while(q.size()) {
    		head=q.front();
    		q.pop();
    		x=head.x,y=head.y,z=head.z;
    		if((x==s/2&&y==s/2)||(x==s/2&&z==s/2))mn=min(mn,dist[x][y][z]);
    		if(mn!=INF) {
    			cout<<mn<<'\n';
    			break;
    		}
    		if(daoman(x,y,n))doit(x-(n-y),n,z);
    		if(daoman(x,z,m))doit(x-(m-z),y,m);
    		if(daoman(y,z,m))doit(x,y-(m-z),m);
    		if(daoman(y,x,s))doit(s,y-(s-x),z);
    		if(daoman(z,x,s))doit(s,y,z-(s-x));
    		if(daoman(z,y,n))doit(x,n,z-(n-y));
    		if(daokong(x,y,n))doit(0,x+y,z);
    		if(daokong(x,z,m))doit(0,y,x+z);
    		if(daokong(y,z,m))doit(x,0,y+z);
    		if(daokong(y,x,s))doit(x+y,0,z);
    		if(daokong(z,x,s))doit(x+z,y,0);
    		if(daokong(z,y,n))doit(x,y+z,0);
    	}
    	if(mn==INF)cout<<"NO"<<'\n';
    }
    int main() {
    	ios::sync_with_stdio(false);
    	cin.tie(NULL);
    	while(cin>>s>>n>>m) {
    		if(!s&&!n&&!m)break;
    		memset(dist,0,sizeof(dist));
    		while(q.size())q.pop();
    		if(s%2)cout<<"NO"<<'\n';
    		else bfs();
    	}
    	return 0;
    }
    
  • 相关阅读:
    nexus 手动更改 私服包
    maven 构建时 错误: 程序包netscape.javascript不存在
    RocketMQ
    NSQ
    beego 实现API自动化文档
    动态追踪技术漫谈
    go vendor管理Golang项目依赖
    consul介绍
    golang rpc介绍
    golang 使用os/exec配合context实现的超时机制
  • 原文地址:https://www.cnblogs.com/yige2019/p/15820966.html
Copyright © 2020-2023  润新知