HDU - 1495 非常可乐(BFS枚举 or 数论)

版权声明:版权归Ordinarv所有 https://blog.csdn.net/ordinarv/article/details/82180410

题目大意

三个cup,容量分别为s,n,m(s=n+m),cup没有刻度(这个真的坑,就是要么倒完要么倒满)。初始状况,s满,n、m空,求能否通过相互之间倒可乐,把可乐平分。能的话,输出最小次数。


分析

每次倒都有6种情况s-n,s-m.....。可以BFS分别枚举每种倒法。很明显s为奇数,NO。

vis也能起到终止作用吧,每种情况都走过被标记了。队列为空,则返回-1,表示不能平分。

要注意 只有当下一状态条件满足并且没有走过时,才让其level+1;

听说数论也能做,但我    不会!


AC Code

#include<bits/stdc++.h>
typedef long long ll;
const int INF=0x3f3f3f3f;
const int maxn=1e2+5;
using namespace std;
int s,n,m;
bool vis[maxn][maxn][maxn];
struct node {
	int s,m,n,level;
};
bool judge(node &tar) {
	int ans=s/2;
	if(tar.s==ans&&tar.n==ans||tar.s==ans&&tar.m==ans||tar.n==ans&&tar.m==ans)
		return 1;	
	return 0;
}
int bfs() {
	if(s%2) return -1;
	memset(vis,0,sizeof(vis));
	queue<node> q;
	node cur,next;
	cur.s=s;
	cur.n=0;
	cur.m=0;
	cur.level=0;
	vis[s][0][0]=1;
	q.push(cur);
	while(!q.empty()) {
		cur=q.front();
		q.pop();
		//6 zhong
		if(cur.s&&n-cur.n>0) { //s->n
			if(cur.s>=(n-cur.n)) { //s能够倒满n
				next.s=cur.s-(n-cur.n);
				next.n=n;				
			}
			else {
				next.s=0;
				next.n=cur.n+cur.s;				
			}
			next.m=cur.m;		
			if(!vis[next.s][next.n][next.m]) {
				next.level=cur.level+1;//要放入if里 
				vis[next.s][next.n][next.m]=1;
				q.push(next);
			}
			if(judge(next))	return next.level;
		}
		//s->m
		if(cur.s&&n-cur.m>0) { //s->n
			if(cur.s>=(m-cur.m)) {
				next.s=cur.s-(m-cur.m);
				next.m=m;				
			}
			else {
				next.s=0;
				next.m=cur.m+cur.s;				
			}
			next.n=cur.n;		
			if(!vis[next.s][next.n][next.m]) {
				next.level=cur.level+1;
				vis[next.s][next.n][next.m]=1;
				q.push(next);
			}
			if(judge(next))	return next.level;
		}
		//n->s
		if(cur.n&&s-cur.s>0) { //s->n
			if(cur.n>=(s-cur.s)) { 
				next.n=cur.n-(s-cur.s);
				next.s=s;				
			}
			else {
				next.n=0;
				next.s=cur.s+cur.n;				
			}
			next.m=cur.m;		
			if(!vis[next.s][next.n][next.m]) {
				next.level=cur.level+1; 
				vis[next.s][next.n][next.m]=1;
				q.push(next);
			}
			if(judge(next))	return next.level;
		}
		//n->m
		if(cur.n&&m-cur.m>0) { //s->n
			if(cur.n>=(m-cur.m)) { 
				next.n=cur.n-(m-cur.m);
				next.m=m;				
			}
			else {
				next.n=0;
				next.m=cur.m+cur.n;				
			}
			next.s=cur.s;		
			if(!vis[next.s][next.n][next.m]) {
				next.level=cur.level+1; 
				vis[next.s][next.n][next.m]=1;
				q.push(next);
			}
			if(judge(next))	return next.level;
		}
		//m->s
		if(cur.m&&s-cur.s>0) { //s->n
			if(cur.m>=(s-cur.s)) { 
				next.m=cur.m-(s-cur.s);
				next.s=s;				
			}
			else {
				next.m=0;
				next.s=cur.s+cur.m;				
			}
			next.n=cur.n;		
			if(!vis[next.s][next.n][next.m]) {
				next.level=cur.level+1; 
				vis[next.s][next.n][next.m]=1;
				q.push(next);
			}
			if(judge(next))	return next.level;
		}
		//m->n
		if(cur.m&&n-cur.n>0) { //s->n
			if(cur.m>=(n-cur.n)) { 
				next.m=cur.m-(n-cur.n);
				next.n=n;				
			}
			else {
				next.m=0;
				next.n=cur.n+cur.m;				
			}
			next.s=cur.s;		
			if(!vis[next.s][next.n][next.m]) {
				next.level=cur.level+1;//要放入if里 
				vis[next.s][next.n][next.m]=1;
				q.push(next);
			}
			if(judge(next))	return next.level;
		}
	}
	return -1;
}
int main() {
	while(~scanf("%d%d%d",&s,&n,&m)&&s+m+n) {
		int ans=bfs();

		if(ans==-1) printf("NO\n");
		else printf("%d\n",ans);
	}
	return 0;
}

猜你喜欢

转载自blog.csdn.net/ordinarv/article/details/82180410