(BFS)FZU.Problem 2188 过河I

 Problem 2188 过河I

Accept: 52    Submit: 131
Time Limit: 3000 mSec    Memory Limit : 32768 KB

 Problem Description

一天,小明需要把x只羊和y只狼运输到河对面。船可以容纳n只动物和小明。每次小明划船时,都必须至少有一只动物来陪他,不然他会感到厌倦,不安。不论是船上还是岸上,狼的数量如果超过羊,狼就会把羊吃掉。小明需要把所有动物送到对面,且没有羊被吃掉,最少需要多少次他才可以穿过这条河?

 Input

有多组数据,每组第一行输入3个整数想x, y, n (0≤ x, y,n ≤ 200)

 Output

如果可以把所有动物都送过河,且没有羊死亡,则输出一个整数:最少的次数。 否则输出 -1 .

 Sample Input

3 3 233 33 3

 Sample Output

11-1

 Hint

第一个样例

次数 船 方向 左岸 右岸(狼 羊)

0: 0 0 3 3 0 0

1: 2 0 > 1 3 2 0

2: 1 0 < 2 3 1 0

3: 2 0 > 0 3 3 0

4: 1 0 < 1 3 2 0

5: 0 2 > 1 1 2 2

6: 1 1 < 2 2 1 1

7: 0 2 > 2 0 1 3

8: 1 0 < 3 0 0 3

9: 2 0 > 1 0 2 3

10: 1 0 < 2 0 1 3

11: 2 0 > 0 0 3 3

 Source

FOJ有奖月赛-2015年03月


/*
题目:2188 过河I
链接:http://acm.fzu.edu.cn/problem.php?pid=2188
题意:小明需要把x只羊和y只狼运输到河对面。船可以容纳n只动物和小明。每次小明划船时,都
    必须至少有一只动物来陪他。不论是船上还是岸上,狼的数量如果超过羊,狼就会把羊吃掉。
    问小明需要把所有动物送到对面,且没有羊被吃掉,最少需要多少次他才可以穿过这条河。
思路:BFS(广度优先搜索)。记录两岸羊跟狼的数量以及步骤数。没有特殊技巧,就是细节比较
    多,细心点就好了,详情见代码。
*/
#include <queue>
#include <cstdio>
#include <cstring>
#include <iostream>
#include <algorithm>
using namespace std;
#define lson l, mid, rt << 1
#define rson mid + 1, r, rt << 1 | 1
#define inf 1000000000
#define LL long long
#define N 210  //数组大小
bool vis[2][N][N];
int x, y, n;
struct node{
    int sw, sh, ew, eh, step;//sw 起始一端狼的数量,sh 起始一端羊的数量,ew 终点一端狼的数量,eh 终点一端羊的数量, step 步骤数
    node(){}
    node(int sw, int sh, int ew, int eh, int step) :sw(sw), sh(sh), ew(ew), eh(eh), step(step){}
};
int bfs()
{
    memset(vis, false, sizeof vis);
    vis[0][y][x] = true;
    queue<node> Q;
    Q.push(node(y, x, 0, 0, 0));//入队
    while (!Q.empty())
    {
        node now = Q.front();//取队首元素
        Q.pop();//出队
        if (now.ew == y && now.eh == x) return now.step;//到达目标,返回步骤数
        int k = (now.step % 2) == 0 ? 1 : -1;//k = 1, 从起始一端到终点一端, k = -1, 从终点一端到起始一端
        for (int i = n; i >= 0; i--)//i,枚举运输狼的数量
        {
            if (now.sw - i * k < 0) continue;//判断不合法情况
            if (now.sw - i * k > y) continue;
            if (now.ew + i * k < 0) continue;
            if (now.ew + i * k > y) continue;
            for (int j = 0; j <= n - i; j == 0 ? (i == 0 ? j = i + 1 : j = i) : j++)//j,枚举运输羊的数量
            {//唯一一种i > j,就是当j = 0的时候,其余情况必须j >= i。
                if (i + j == 0) continue;//运输过程中必须要有动物
                if (now.sh - j * k < 0) continue;//判断不合法情况
                if (now.sh - j * k > x) continue;
                if (now.eh + j * k < 0) continue;
                if (now.eh + j * k > x) continue;
                if (now.sw - i * k > now.sh - j * k && now.sh - j * k != 0) continue;//起始一端狼的数量大于羊的数量且羊的数量不为零的时候不合法
                if (now.ew + i * k > now.eh + j * k && now.eh + j * k != 0) continue;//终点一端狼的数量大于羊的数量且羊的数量不为零的时候不合法
                if (vis[(now.step + 1) % 2][now.sw - i * k][now.sh - j * k]) continue;//该情况已经出现过不合法
                vis[(now.step + 1) % 2][now.sw - i * k][now.sh - j * k] = true;
                Q.push(node(now.sw - i * k, now.sh - j * k, now.ew + i * k, now.eh + j * k, now.step + 1));//合法,入队
            }
        }
    }
    return -1;
}
int slove(int num)
{
    int res = 0;
    while (num > n - 1)
    {
        if (num == n)
            res++, num = 0;
        else res += 2, num -= n - 1;
    }
    if (num > 0) res++;
    return res;
}
int main()
{
    while (~scanf("%d%d%d", &x, &y, &n))
    {
        if (x == 0 && y == 0) printf("0\n");
        else if (n == 0) printf("-1\n");
        else if (n == 1)
        {
            if (x + y == 1) printf("1\n");
            else printf("-1\n");
        }
        else if (y == 0)
            printf("%d\n", slove(x));
        else if (x == 0)
            printf("%d\n", slove(y));
        else if (y > x) printf("-1\n");
        else printf("%d\n", bfs());
    }
    return 0;
}
 


评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值