hdu 1495 非常可乐

链接:点击打开链接

题意:给你三个容器让你平分可乐,求最少的步数。

思路:一看到求最少步数,就想到了广搜,但是没有思路,但看别人分情况,瞬间就明白啦。可以S->N,S->M,N->S,N->M,M->S,M->N这六种情况讨论就行,每种又有倒完和倒不完两种情况,直到出现两个容器都有S/2,这就是最少步数。但S是奇数时是不能平分的,三个容器的容积都是整数。不一定偶数就能可以平分,我因为少了这个条件,而WA一次。。

 

#include<iostream>
#include<cstdio>
#include<cstring>
#include<queue>
using namespace std;
int s,n,m;
struct node{
	int a,b,c;
	int count;
	};
bool vis[110][110][110];
void bfs(){
	int i;
	queue<node>Q;
	node q,p;
	p.a=s;
	p.b=0;
	p.c=0;
	p.count=0;
	memset(vis,false,sizeof(vis));
	vis[p.a][p.b][p.c]=true;
	Q.push(p);
	while(!Q.empty()){
		p=Q.front();
		Q.pop();
		if((p.a==s/2&&p.b==s/2)||(p.a==s/2&&p.c==s/2)||(p.b==s/2&&p.c==s/2)){
			printf("%d\n",p.count);
			return; 
			}
		 if(p.a!=0){ 
				if(p.a>n-p.b){//s->n
					q.a=p.a-(n-p.b);
					q.b=n;
					q.c=p.c;
					q.count=p.count+1;
					}
					else{
						q.a=0;
					    q.b=p.b+p.a;
						q.c=p.c;
						q.count=p.count+1;	
						}
					if(!vis[q.a][q.b][q.c]){
						vis[q.a][q.b][q.c]=true;
						Q.push(q);
						}
				 if(p.a>m-p.c){//s->m
						q.a=p.a-(m-p.c);
						q.b=p.b;
						q.c=m;
						q.count=p.count+1;
						}
					else{
						q.a=0;
						q.b=p.b;
						q.c=p.c+p.a;
						q.count=p.count+1;
						}
					if(!vis[q.a][q.b][q.c]){
						vis[q.a][q.b][q.c]=true;
						Q.push(q);
						}					
				}
			if(p.b!=0){
				if(p.b>s-p.a){//n->s
					q.a=s;
					q.b=p.b-(s-p.a);
					q.c=p.c;
					q.count=p.count+1;
					}
					else{
						q.a=p.a+p.b;
						q.b=0;
						q.c=p.c;
						q.count=p.count+1;
						}
				if(!vis[q.a][q.b][q.c]){
					vis[q.a][q.b][q.c]=true;
					Q.push(q);
					}		
				 if(p.b>m-p.c){//n->m
						q.a=p.a;
						q.b=p.b-(m-p.c);
						q.c=m;
						q.count=p.count+1;
						}
						else{
							q.a=p.a;
							q.b=0;
							q.c=p.c+p.b;
							q.count=p.count+1;
							}
				  if(!vis[q.a][q.b][q.c]){
						vis[q.a][q.b][q.c]=true;
						Q.push(q);
						}				
				}
			if(p.c!=0){
				if(p.c>s-p.a){//m->s
					q.a=s;
					q.b=p.b;
					q.c=p.c-(s-p.a);
					q.count=p.count+1;
					}
					else{
						q.a=p.a+p.c;
						q.b=p.b;
						q.c=0;
						q.count=p.count+1;
						}
				if(!vis[q.a][q.b][q.c]){
					vis[q.a][q.b][q.c]=true;
					Q.push(q);
					}
				 if(p.c>n-p.b){//m->n
						q.a=p.a;
						q.b=n;
						q.c=p.c-(n-p.b);
						q.count=p.count+1;
						}
						else{
							q.a=p.a;
							q.b=p.b+p.c;
							q.c=0;
							q.count=p.count+1;
							}
				 if(!vis[q.a][q.b][q.c]){
						vis[q.a][q.b][q.c]=true;
						Q.push(q);
						}				 		
				}		
		}
		printf("NO\n");
		return;
	}
int main(){
	while(~scanf("%d %d %d",&s,&n,&m)){
		if(s==0&&n==0&&m==0)
		break;
		if(s%2==1)
		printf("NO\n");
		else
		bfs();
		}
		return 0;
	}	

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值