HDU1495:非常可乐

HDU1495:非常可乐

题目描述
大家一定觉的运动以后喝可乐是一件很惬意的事情,但是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

思路
简单的模拟+bfs求最优解

代码如下

#include <iostream> 
#include <cstdio>
#include <cstdlib>
#include <cmath>
#include <fstream>
#include <algorithm>
#include <climits>
#include <cstring>
#include <string>
#include <set>
#include <queue>
#include <stack>
#include <vector>
#include <list>
#include<sstream>
#include<ctime>
using namespace std;  
int S,N,M,flag;  
struct node    //当前三个容器中的量,和到该状态所用操作次数
{
    int s;
    int n;
    int m;
    int step;
};
queue<node> que;
int f[105][105][105];
int panduan(int a,int b,int c)   // 判断是否平分
{                                // 如果三个容器中有两个的量相等且第个容器中的量为0说明已经平分
    if(a==b&&c==0) return 1;
    if(a==c&&b==0) return 1;
    if(b==c&&a==0) return 1;
    return 0;
}
void bfs()  
{  
   while(!que.empty())
   {
      node u=que.front();
      que.pop();
      if(panduan(u.s,u.n,u.m)) // 如果已经平分,则输出结果,结束
      {
        flag=1;
        cout<<u.step<<endl;
        return; 
      }

      node v;                 //有6种不同操作

      if(u.s!=0&&u.n!=N) // 1.s倒给n 
      {
        if(u.s+u.n<=N)
        {
            v.s=0;
            v.n=u.s+u.n;
            v.m=u.m;
            v.step=u.step+1;
            if(f[v.s][v.n][v.m]==0)
            {
               que.push(v);
               f[v.s][v.n][v.m]=1;
            }
        }
        else if(u.s+u.n>N)
        {
            v.s=u.s+u.n-N;
            v.n=N;
            v.m=u.m;
            v.step=u.step+1;
            if(f[v.s][v.n][v.m]==0)
            {
               que.push(v);
               f[v.s][v.n][v.m]=1;
            }
        }
      }


      if(u.n!=0&&u.s!=S) //2.n倒给s
      {
        if(u.s+u.n<=S)
        {
            v.s=u.s+u.n;
            v.n=0;
            v.m=u.m;
            v.step=u.step+1;
            if(f[v.s][v.n][v.m]==0)
            {
               que.push(v);
               f[v.s][v.n][v.m]=1;
            }
        }
        else if(u.s+u.n>S)
        {
            v.s=S;
            v.n=u.s+u.n-S;
            v.m=u.m;
            v.step=u.step+1;
            if(f[v.s][v.n][v.m]==0)
            {
               que.push(v);
               f[v.s][v.n][v.m]=1;
            }
        }
       } 

       if(u.s!=0&&u.m!=M)  //3.s倒给m
       {
           if(u.s+u.m<=M)
           {
               v.s=0;
               v.m=u.s+u.m;
               v.n=u.n;
               v.step=u.step+1;
               if(f[v.s][v.n][v.m]==0)
               {
                  que.push(v);
                  f[v.s][v.n][v.m]=1;
               }
            }
            else if(u.s+u.m>M)
            {
               v.s=u.s+u.m-M;
               v.m=M;
               v.n=u.n;
               v.step=u.step+1;
               if(f[v.s][v.n][v.m]==0)
               {
                  que.push(v);
                  f[v.s][v.n][v.m]=1;
               }
            }
        } 
       if(u.m!=0&&u.s!=S)  //4.m倒给s
       {
           if(u.s+u.m<=S)
           {
               v.m=0;
               v.s=u.s+u.m;
               v.n=u.n;
               v.step=u.step+1;
               if(f[v.s][v.n][v.m]==0)
               {
                  que.push(v);
                  f[v.s][v.n][v.m]=1;
               }
            }
            else if(u.s+u.m>S)
            {
               v.m=u.s+u.m-S;
               v.s=S;
               v.n=u.n;
               v.step=u.step+1;
               if(f[v.s][v.n][v.m]==0)
               {
                  que.push(v);
                  f[v.s][v.n][v.m]=1;
               }
            }
        } 

        if(u.n!=0&&u.m!=M) //5.把n倒给m
        {
            if(u.n+u.m<=M)
            {
               v.m=u.m+u.n;
               v.n=0;
               v.s=u.s;
               v.step=u.step+1;
               if(f[v.s][v.n][v.m]==0)
               {
                  que.push(v);
                  f[v.s][v.n][v.m]=1;
               }
            }
            else if(u.n+u.m>M)
            {
               v.m=M;
               v.n=u.n+u.m-M;
               v.s=u.s;
               v.step=u.step+1;
               if(f[v.s][v.n][v.m]==0)
               {
                  que.push(v);
                  f[v.s][v.n][v.m]=1;
               }
            }
         }

         if(u.m!=0&&u.n!=N)   // 6.把m倒给n 
         {
            if(u.m+u.n<=N)
             {
                v.m=0;
                v.n=u.n+u.m;
                v.s=u.s;
                v.step=u.step+1;
                if(f[v.s][v.n][v.m]==0)
                {
                  que.push(v);
                  f[v.s][v.n][v.m]=1;
                }
              } 
              else if(u.m+u.n>N)
              {
                v.n=N;
                v.m=u.m+u.n-N;
                v.s=u.s;
                v.step=u.step+1;
                if(f[v.s][v.n][v.m]==0)
                {
                  que.push(v);
                  f[v.s][v.n][v.m]=1;
                }
              }
          } 
   }
} 
int main()  
{  
    while(cin>>S>>N>>M)
    {
        flag=0;
        if(!(S+N+M))
        break;
        if(S%2!=0)  //如果初始量不能被2整除,则不可能被平分
        cout<<"NO\n";
        else 
        {
            memset(f,0,sizeof(f));  //初始化
            while(!que.empty())
            que.pop();
            node u;
            u.s=S;
            u.m=0;
            u.n=0;
            u.step=0;
            que.push(u);  //将初始状态入队
            bfs();
            if(flag==0)   //如果无解
            cout<<"NO\n";
        }
    }
    return 0;  
}  
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值