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;
}

浙公网安备 33010602011771号