FZU 2188 BFS

最多只有200个羊,200狼,所以最多只有200*200种状态

再加上题上的限制条件,不管在任何地方,羊的个数不能少于狼,除非羊为0,可以剪枝掉大量状态

所以对所有情况进行BFS即可

要注意一些判定条件

1:不管在左岸还是右岸或船上,羊的个数不能少于狼,除非羊为0

2:起始时,若狼的个数大于羊,则无解(注意数据存在没有羊只有狼的情况)

3:在移动中直接判断状态是否合法,能提供大量剪枝


#include "stdio.h"
#include "string.h"
#include "queue"
using namespace std;

struct node
{
    int x,y,t,s;
};

int used[210][210][2],x,y,n;
int bfs()
{
    queue<node>q;
    node cur,next;
    int i,j,tx,ty;
    if (x<y && x!=0) return -1;
    cur.x=x;
    cur.y=y;
    cur.t=0;
    cur.s=0;
    memset(used,0,sizeof(used));
    used[x][y][0]=1; // 0 代表当前人在左岸,1代表在右岸
    q.push(cur);

    while (!q.empty())
    {
        cur=q.front();
        q.pop();
        if (cur.s==0)
        {

        for (i=0;i<=n && i<=cur.x;i++)
            for (j=0;j<=cur.y && (j<=i || i==0) ;j++)
            {
                if (i+j==0) continue;
                if (i+j>n) break; // 狼+羊大于船载量
                if (cur.x-i<cur.y-j && cur.x-i!=0) continue; // 移动后原来岸上羊<狼
                tx=x-cur.x;
                ty=y-cur.y;
                if (tx+i<ty+j && tx+i!=0) continue; // 移动后对面岸上羊<狼
                next.x=cur.x-i;
                next.y=cur.y-j;
                next.s=1;
                if (used[next.x][next.y][1]==0)
                {
                    used[next.x][next.y][1]=1;
                    next.t=cur.t+1;
                    if (next.x==0 && next.y==0)
                        return next.t;
                    q.push(next);
                }
            }
        }
        else
        {


        tx=x-cur.x;
        ty=y-cur.y;
        for (i=0;i<=n && i<=tx;i++)
            for (j=0;(j<=i || i==0)  && j<=ty;j++)
            {
                if (i+j==0) continue;
                if (i+j>n) break;
                if (tx-i<ty-j&& tx-i!=0) continue;
                next.x=cur.x+i;
                next.y=cur.y+j;
                next.s=0;
                if (next.x<next.y && next.x!=0) continue;
                if (used[next.x][next.y][0]==0)
                {
                    used[next.x][next.y][0]=1;
                    next.t=cur.t+1;
                    q.push(next);
                }

            }
        }
    }
    return -1;
}
int main()
{
    while (scanf("%d%d%d",&x,&y,&n)!=EOF)
    {
        printf("%d\n",bfs());
    }
    return 0;
}



评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值