HDU1495 非常可乐 BFS

非常可乐

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


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

   找了很久规律还是无果(其实肯定有的),还是暴力搜索吧,对于三个容器,用一个结构题存储三个状态,每次寻找到一个状态的时候,判定是否已经满足要求。在暴力的时候,我找了六个状态,不知道是否可以再减少状态量,这里对于有6个状态是没有必要的,那就是对于单前容器,不要一次进行两次倒置,即将其分给另外两个容器(如果可行的话),这样会大大增加代码量,其实这个状态能够在下一次的计算中能够暴力到。搜索时记得记忆化,不然会形成死循环。
  代码如下:
#include <stdio.h>
#include <math.h>
#include <queue>
#include <cstring>
using namespace std;

struct Node
{
	int s, n, m, ti;
}info;

int S, N, M, hash[105][105][105];

inline bool legal( Node t )
{
    int cnt= 0;
    if( t.s== S/ 2 )
    {
        cnt++;
    }
    if( t.n== S/ 2 )
    {
        cnt++;
    }
    if( t.m== S/ 2 )
    {
        cnt++;
    }
    if( cnt== 2 )
    {
        return true;
    }
    return false;
}

bool BFS( int &ans )
{
	queue< Node >q;
	info.s= S, info.m= 0, info.n= 0, info.ti= 0;
	hash[S][0][0]= 0;
	q.push( info );
	while( !q.empty() )
	{
		Node pos= q.front();
		q.pop();
		if( legal( pos ) )
		{
			ans= pos.ti;
			return true; 
		}
		if( pos.s> 0 )
		{
			if( pos.n< N )
			{
				int temp= min( pos.s, N- pos.n );
				info.s= pos.s- temp;
				info.n= pos.n+ temp;
				info.m= pos.m;
				info.ti= pos.ti+ 1;
				if( pos.ti+ 1< hash[info.s][info.n][info.m] )
				{
					hash[info.s][info.n][info.m]= pos.ti;
					q.push( info );
				}
			}
			if( pos.m< M )
			{
				int temp= min( pos.s, M- pos.m );
				info.s= pos.s- temp;
				info.m= pos.m+ temp;
				info.n= pos.n;
				info.ti= pos.ti+ 1;
				if( pos.ti+ 1< hash[info.s][info.n][info.m] )
				{
					hash[info.s][info.n][info.m]= pos.ti;
					q.push( info );
				}
			}
		}
		if( pos.n> 0 )
		{
			if( pos.s< S )
			{
				int temp= min( pos.n, S- pos.s );
				info.s= pos.s+ temp;
				info.n= pos.n- temp;
				info.m= pos.m;
				info.ti= pos.ti+ 1;
				if( pos.ti+ 1< hash[info.s][info.n][info.m] )
				{
					hash[info.s][info.n][info.m]= pos.ti;
					q.push( info );
				}
			}
			if( pos.m< M )
			{
				int temp= min( pos.n, M- pos.m );
				info.n= pos.n- temp;
				info.m= pos.m+ temp;
				info.s= pos.s;
				info.ti= pos.ti+ 1;
				if( pos.ti+ 1< hash[info.s][info.n][info.m] )
				{
					hash[info.s][info.n][info.m]= pos.ti;
					q.push( info );
				}
			}
		}
		if( pos.m> 0 )
		{
			if( pos.s< S )
			{
				int temp= min( pos.m, S- pos.s );
				info.s= pos.s+ temp;
				info.m= pos.m- temp;
				info.n= pos.n;
				info.ti= pos.ti+ 1;
				if( pos.ti+ 1< hash[info.s][info.n][info.m] )
				{
					hash[info.s][info.n][info.m]= pos.ti;
					q.push( info );
				}
			}
			if( pos.n< N )
			{
				int temp= min( pos.m, N- pos.n );
				info.m= pos.m- temp;
				info.n= pos.n+ temp;
				info.s= pos.s;
				info.ti= pos.ti+ 1;
				if( pos.ti+ 1< hash[info.s][info.n][info.m] )
				{
					hash[info.s][info.n][info.m]= pos.ti;
					q.push( info );
				}
			}
		}
	}
	return false;
}

int main()
{
	while( scanf( "%d %d %d", &S, &N, &M ), S| N| M )
	{
		if( S& 1 )
		{
			printf( "NO\n" );
			continue;
		}
		int ans;
		memset( hash, 0x7f, sizeof( hash ) ); 
		if( BFS( ans ) )
		{
		    printf( "%d\n", ans );
		}
		else
		{
		    puts( "NO" );
		}
	}
	return 0;
}
原文地址:https://www.cnblogs.com/Lyush/p/2131191.html