1. 程式人生 > >HDU - 1495 非常可樂(BFS列舉 or 數論)

HDU - 1495 非常可樂(BFS列舉 or 數論)

題目大意

三個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;
}