zoukankan      html  css  js  c++  java
  • HDU 1495-非常可乐(BFS+模拟)

    非常可乐

    Time Limit: 2000/1000 MS (Java/Others) Memory Limit: 32768/32768 K (Java/Others)
    Total Submission(s): 36199 Accepted Submission(s): 14090

    Problem Description

    大家一定觉的运动以后喝可乐是一件很惬意的事情,但是seeyou却不这么认为。因为每次当seeyou买了可乐以后,阿牛就要求和seeyou一起分享这一瓶可乐,而且一定要喝的和seeyou一样多。但seeyou的手中只有两个杯子,它们的容量分别是N 毫升和M 毫升 可乐的体积为S (S<101)毫升 (正好装满一瓶) ,它们三个之间可以相互倒可乐 (都是没有刻度的,且 S==N+M,101>S>0,N>0,M>0) 。聪明的ACMER你们说他们能平分吗?如果能请输出倒可乐的最少的次数,如果不能输出"NO"。

    Input

    三个整数 : S 可乐的体积 , N 和 M是两个杯子的容量,以"0 0 0"结束。

    Output

    如果能平分的话请输出最少要倒的次数,否则输出"NO"。

    Sample Input

    7 4 3
    4 1 3
    0 0 0

    Sample Output

    NO
    3

    题目链接

    解题思路:
    这道题是HDU上的题,主要用到了BFS,题意是给你一瓶可乐和两个杯子,可乐瓶的容积和两个杯子的和相同,让你检查是否能通过相互倒可乐来达到平分的目的,这里的平分是指三个容器中有两个容器的可乐是相等的,并且等于1/2可乐原本的量。所以当可乐的容积是奇数时,一定不能平分,直接输出“NO”,否则bfs,我们需要先判断几种情况:即怎样到可乐,一共有6种情况(以变量的方式说明):S->N S->M N->S N->M M->S M->N这六种,倒可乐时,我们判断一下,拿一开始的4 1 3 为例(这里只列举正确答案的倒法),刚开始三个杯子的状态是4 0 0 ,因为s的余量大于m的余量,所以向m中到可乐,直到s全倒掉或者达到m的极限。得到1 0 3之后m 向 n倒,得到1 1 2,n再向s中倒,最终得到2 0 2 可以平分,搜索到此结束,最后输出ans;AC代码:

    #include <cstdio>
    #include <iostream>
    #include <algorithm>
    #include <cstring>
    #include <queue>
    using namespace std;
    const int _max=105;
    int book[_max][_max][_max];//标记数组,防止重复扩充
    struct node {int s,n,m,step;};
    int s,n,m,ans;
    int main()
    {
    	void bfs();
    	while(cin>>s>>n>>m)
    	{
    		if(s==0&&n==0&&m==0)
    		  break;
    		if(s&1)//判断奇偶
    		{
    			cout<<"NO"<<endl;
    			continue;
    		}
    		ans=-1;//ans初始化为-1
    		bfs();
    		if(ans<0)
    		  cout<<"NO"<<endl;
    		else  
    		  cout<<ans<<endl;
    	}
    	return 0;
    }
    void bfs()
    {
    	int s2=s>>1;//最终要平分的量
    	queue<node >q;
    	memset(book,0,sizeof(book));//最初都没有扩充过
    	node t;
    	t.s=s;
    	t.n=t.m=t.step=0;
    	q.push(t);
    	book[t.s][t.n][t.m]=1;
    	while(!q.empty())
    	{
    		node f=q.front();
    		if((f.s==f.n&&f.s==s2)||(f.n==f.m&&f.n==s2)||(f.s==f.m&&f.m==s2))
    		{
    			//cout<<f.s<<" "<<f.n<<" "<<f.m<<endl;
    			ans=f.step;
    			return;
    		}
    		if(f.s&&n-f.n>0)//s->n,枚举6种情况并判断是否可以扩充
    		{
    			if(f.s>n-f.n)
    			{
    			    t.s=f.s-(n-f.n);//这里一定要好好检查,因为这个点WA了5次,调试了一下午...
    			    t.n=n;
    			    t.m=f.m;
    			}
    			else
    			{
    				t.s=0;
    				t.n=f.s+f.n;
    				t.m=f.m;
    			}
    			if(!book[t.s][t.n][t.m])
    			{
    				book[t.s][t.n][t.m]=1;
    				t.step=f.step+1;
    				q.push(t);
    			}
    		}
    		if(f.s&&m-f.m>0)
    		{
    			if(f.s>m-f.m)
    			{
    			    t.s=f.s-(m-f.m);
    			    t.n=f.n;
    			    t.m=m;
    			}
    			else
    			{
    				t.s=0;
    				t.n=f.n;
    				t.m=f.s+f.m;
    			}
    			if(!book[t.s][t.n][t.m])
    			{
    				book[t.s][t.n][t.m]=1;
    				t.step=f.step+1;
    				q.push(t);
    			}
    		}
    		if(f.n&&s-f.s>0)
    		{
    			if(f.n>s-f.s)
    			{
    			    t.s=s;
    			    t.n=f.n-(s-f.s);
    			    t.m=f.m;
    			}
    			else
    			{
    				t.s=f.s+f.n;
    				t.n=0;
    				t.m=f.m;
    			}
    			if(!book[t.s][t.n][t.m])
    			{
    				book[t.s][t.n][t.m]=1;
    				t.step=f.step+1;
    				q.push(t);
    			}
    		}
    		if(f.n&&m-f.m>0)
    		{
    			if(f.n>m-f.m)
    			{
    			    t.s=f.s;
    			    t.n=f.n-(m-f.m);
    			    t.m=m;
    			}
    			else
    			{
    				t.s=f.s;
    				t.n=0;
    				t.m=f.n+f.m;
    			}
    			if(!book[t.s][t.n][t.m])
    			{
    				book[t.s][t.n][t.m]=1;
    				t.step=f.step+1;
    				q.push(t);
    			}
    		}
    		if(f.m&&n-f.n>0)
    		{
    			if(f.m>n-f.n)
    			{
    			    t.s=f.s;
    			    t.n=n;
    			    t.m=f.m-(n-f.n);
    			}
    			else
    			{
    				t.s=f.s;
    				t.n=f.n+f.m;
    				t.m=0;
    			}
    			if(!book[t.s][t.n][t.m])
    			{
    				book[t.s][t.n][t.m]=1;
    				t.step=f.step+1;
    				q.push(t);
    			}
    		}
    		if(f.m&&s-f.s>0)
    		{
    			if(f.m>s-f.s)
    			{
    			    t.s=s;
    			    t.n=f.n;
    			    t.m=f.m-(s-f.s);
    			}
    			else
    			{
    				t.s=f.s+f.m;
    				t.n=f.n;
    				t.m=0;
    			}
    			if(!book[t.s][t.n][t.m])
    			{
    				book[t.s][t.n][t.m]=1;
    				t.step=f.step+1;
    				q.push(t);
    			}
    		}
    		q.pop();//每次扩充完记得出队
    	}
    	return;
    }
    
  • 相关阅读:
    HAProxy、Keepalived 在 Ocatvia 的应用实现与分析
    Octavia 的 HTTPS 与自建、签发 CA 证书
    Octavia 创建 loadbalancer 的实现与分析
    OpenStack Rally 质量评估与自动化测试利器
    自建 CA 中心并签发 CA 证书
    Failed building wheel for netifaces
    通过 vSphere WS API 获取 vCenter Datastore Provisioned Space 置备空间
    OpenStack Placement Project
    我们建了一个 Golang 硬核技术交流群(内含视频福利)
    没有图形界面的软件有什么用?
  • 原文地址:https://www.cnblogs.com/Hayasaka/p/14294315.html
Copyright © 2011-2022 走看看