HDU1495非常可乐

题目的思路还是很简单的:

因为要求最优解,广度优先搜索,对倒酒的六种操作进行遍历就行了。

然而:

在这个题上作者至少卡了小半天。下面就是作者找到的一些WA点。1.在记录是否被遍历过的状态时,用vis[N][N],来记录是否被遍历过。因为确定了其中两个瓶子,第三个瓶子的状态自然就知道了。关键时,记录的时候,要用后两个瓶子的装酒状态,因为,如果用前两个瓶子的装酒状态的话。s里的酒比a和b瓶子里的酒都要多,若N太小会溢出。而若N太大可能会MLT或者TL。2.广度优先搜索一定会有一个出栈的过程。一定要养成一个良好的编代码的习惯。3.思路一定要清晰,在进行状态变化的时候,一定要注意,不要GG了。

代码如下:

#include <iostream>
#include<queue>
#include<cstring>
#include<algorithm>
#include<cstdio>
using namespace std;
#define N 105
//排查了一上午的bug之一
//迷宫的规模
struct node{
int  a,b,s;
int step;
}ST;
//记录两种状态
//1.记录该步的状态
//2.步数
int a,b,s;
int vis[N][N];
//标记该种状态是否被走过
//广搜队列
int bfs()
{
        queue<node> q;
        ST.s=s;
        ST.a=0;
        ST.b=0;
        ST.step=0;
        q.push(ST);
        vis[0][0]=1;
        while(!q.empty())
    {
        if(q.front().a==s/2&&q.front().s==s/2)
        {
            return q.front().step;
        }
        node tmp;
        //tmp用于暂时储存状态
        int S=q.front().s;
        int A=q.front().a;
        int B=q.front().b;
        int Step=q.front().step;
        int C;
        //广度试探
        if(S&&A!=a)//s->a
        {
            C=a-A;
            if(S>=C)tmp.s=S-C,tmp.a=a;
            else tmp.s=0,tmp.a=A+S;
            tmp.b=B;tmp.step=Step+1;
            if(!vis[tmp.a][tmp.b]){
            vis[tmp.a][tmp.b]=1;
            q.push(tmp);
          }
        }
       if(S&&B!=b)//s->b
       {
        C=b-B;
        if(S>=C)tmp.s=S-C,tmp.b=b;
        else tmp.s=0,tmp.b=B+S;
        tmp.a=A;tmp.step=Step+1;
       if(!vis[tmp.a][tmp.b]){
        vis[tmp.a][tmp.b]=1;
        q.push(tmp);
        }
        }
       if(A&&S!=s)//a->s
        {
            C=s-S;
        if(A>=C)tmp.a=A-C,tmp.s=s;
        else tmp.a=0,tmp.s=S+A;
        tmp.b=B;tmp.step=Step+1;
            if(!vis[tmp.a][tmp.b]){
            vis[tmp.a][tmp.b]=1;
            q.push(tmp);}
        }

         if(B&&S!=s)//b->s
        {
            C=s-S;
      if(C<=B) tmp.b=B-C,tmp.s=s;
      else tmp.b=0,tmp.s=S+B;
       tmp.a=A;tmp.step=Step+1;
            if(!vis[tmp.a][tmp.b]){
            vis[tmp.a][tmp.b]=1;
            q.push(tmp);}
        }

            if(B&& A!=a)//b->a
        {
            C=a-A;
        if(C<=B)tmp.b=B-C,tmp.a=a;
        else tmp.b=0,tmp.a=A+B;
        tmp.s=S;tmp.step=Step+1;
            if(!vis[tmp.a][tmp.b]){
            tmp.step=Step+1;
            vis[tmp.a][tmp.b]=1;
            q.push(tmp);}
        }

       if(A&&B!=b)//a->b
        {
            C=b-B;
        if(C<=A) tmp.a=A-C,tmp.b=b;
        else tmp.a=0,tmp.b=B+A;//排查到的bug之一
        tmp.s=S;tmp.step=Step+1;
            if(!vis[tmp.a][tmp.b]){
            vis[tmp.a][tmp.b]=1;
            q.push(tmp);}
            }
     q.pop();//排除了一上午的bug
     //侮辱智商了
   }
   return 0;
}
int main()
{
    while(cin>>s>>a>>b,s+a+b)//初始化迷宫
    {
        memset(vis,0,sizeof(vis));
        //初始化记录状态的数组
        if(s%2==1){cout<<"NO"<<endl;continue;}
        if(a<b)swap(a,b);
        int ans;
        ans= bfs();
        if(!ans)cout<<"NO"<<endl;
        else cout<<ans<<endl;
    }
    return 0;
}
  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值