Sheep Eat Wolves

Sheep Eat Wolves

状态定义,bfs

问题描述

农夫有 (x) 只羊和 (y) 只狼,需要把羊全部运到河对岸。船每次最多带 (p) 只动物,且必须由农夫驾驶。
如果没有农夫看管,且一侧同时有狼和羊,当狼的数量严格大于羊的数量加 (q) 时,狼会吃掉羊。
求最少需要多少次过河才能把所有羊安全运到对岸,如果无法完成则输出 -1。

解题思路

由于动物数量上限较小((x, y \le 100)),且每次选择带走的动物数量组合有限,可以直接采用 广度优先搜索 (BFS) 寻找最少过河次数。

1. 状态定义

使用三元组 (a, b, t) 表示当前状态:

  • (a):当前左岸的羊的数量
  • (b):当前左岸的狼的数量
  • (t):农夫的位置((0) 表示在左岸,(1) 表示在右岸)

初始状态为 (x, y, 0),距离(过河次数)为 0。

2. 目标状态

当左岸羊的数量为 (0),且农夫在右岸时,即 a == 0 && t == 1,说明所有羊已经安全到达右岸(左岸只剩狼,且农夫在看管右岸),此时当前距离即为答案。

3. 安全检查

当农夫驾驶船离开某一岸时,该岸处于“无农夫看管”状态,必须满足安全条件:

  • 若该岸羊的数量为 (0),绝对安全;
  • 若该岸羊的数量大于 (0),则要求该岸狼的数量 (\le) 羊的数量 (+ q)。
#include<bits/stdc++.h>
using namespace std;
using ll = long long;
using pii = pair<int, int>;
using tpi = tuple<int, int, int>;

int dist[105][105][2];

void solve() {
    int x, y, p, q; cin >> x >> y >> p >> q;
    memset(dist, -1, sizeof(dist));
    dist[x][y][0] = 0;

    auto check = [&](int s, int w) {
        if(s == 0) return true;
        return w <= s + q;
    };

    queue<tpi> que; que.push({x, y, 0});
    while(!que.empty()) {
        auto [a, b, t] = que.front(); que.pop();
        int d = dist[a][b][t];
        if(a == 0 && t == 1) {
            cout << d << "\n";
            return;
        }

        if(t == 0) {
            for(int i = 0; i <= min(a, p); i ++) {
                for(int j = 0; j <= min(b, p - i); j ++) {
                    int na = a - i, nb = b - j;
                    if(!check(na, nb)) continue; //左岸不安全
                    if(dist[na][nb][1] == -1) {
                        dist[na][nb][1] = d + 1;
                        que.push({na, nb, 1});
                    }
                }
            }
        }
        else {
            int rx = x - a, ry = y - b;
            for(int i = 0; i <= min(rx, p); i ++) {
                for(int j = 0; j <= min(ry, p - i); j ++) {
                    int na = a + i, nb = b + j; // 转移后左岸数
                    if(!check(x - na, y - nb)) continue; //右岸不安全
                    if(dist[na][nb][0] == -1) {
                        dist[na][nb][0] = d + 1;
                        que.push({na, nb, 0});
                    }
                }
            }
        }
    }
    cout << -1 << "\n";
}

int main() {
    ios::sync_with_stdio(false); cin.tie(0); cout.tie(0);
    int _ = 1; //cin >> _;
    while(_--) solve();
    return 0;
}
posted @ 2026-11-03 22:16  thenrify  阅读(2)  评论(0)    收藏  举报