河的左岸有n个野人和n个传教士,当传教士小于野人数量,传教士就会被吃掉,有一个能载m个人的船,请问最少多少次才能将野人和传教士送到右岸?
注意点:船不会自己开,每次都需要有一个人在船上。
状态判断:
- 是否有那么多人可以放到船上;
- 船上的野人数不能多于传教士数;
- 当传教士/野人在岸数不为0/n时,野人和传教士的数目必须相等。
#include <iostream>
using namespace std;
//记录左岸的状态
struct State {
int m; //传教士
int c; //野人
int boat; //船的位置
int count; //移动次数
};
int solve(int n,int m) {
//记录每次走的方式,防止重复
int record[11][11][2];
//循环队列
State queue[5] = {0};
int head = 0;
int tail = 0;
//初始状态
State init = { n,n,1,0 };
queue[tail] = init;
tail = (tail + 1) % 5;
//开始bfs
while (head != tail) {
State s = queue[head];
head = (head + 1) % 5;
cout << "传教士:" << s.m << "," << "野人:" << s.c << "," << "船的位置:" << s.boat << "," << "次数:" << s.count << endl;
//左岸没有人时返回计数
if (s.c == 0 && s.m == 0) {
return s.count;
}
if (record[s.m][s.c][s.boat] == 1) {
return -1;
}
record[s.m][s.c][s.boat] = 1;
//在左岸时
if (s.boat == 1) {
for (int i = m; i >= 1; i--) {//上船i个人
if (i > s.m + s.c) continue; //人不够
for (int j = i; j >= 0; j--) {
if (j > s.c || i - j > s.m) continue; //人不够
else if (j != i && j > i - j) continue; //船上并非全是野人,并且野人数更多
else if (s.m - (i - j) != 0 && s.m - (i - j) != n && s.m - (i - j) != s.c - j) continue; // 两岸剩下的传教士不为0也不为n,且传教士和野人数量不相等(这样两边必有一边会被野人吃)
else if (record[s.m - (i - j)][s.c - j][0] == 1) continue; //状态被记录过
else if (s.m - (i - j) == 0 && s.c - j == 0) return s.count + 1; //状态人数变为0,返回计数
State next = { s.m - (i - j), s.c - j ,0,s.count + 1};
queue[tail] = next;
tail = (tail + 1) % 5;
}
}
}
else {//在右岸时(因为目的地是右岸,所以顶多送两个人到左岸(为了将野人送过去))
for (int i = 1; i <= 2; i++) {
if (i > 2 * n - s.m + s.c) continue; //人不够
for (int j = i; j >= 1; j--) {
if (j > n - s.c || i - j > n - s.m) continue; //人不够
else if (j != i && j > i - j) continue; //船上并非全是野人,并且野人数更多
else if (n - s.m - (i - j) != 0 && s.m != 0 && n - s.m - (i - j) != n - s.c - j) continue; //两岸剩下的传教士不为0也不为n,且传教士和野人数量不相等
else if (record[s.m + (i - j)][s.c + j][1] == 1) continue; //状态被记录过
State next = { s.m + (i - j), s.c + j ,1,s.count + 1 };
queue[tail] = next;
tail = (tail + 1) % 5;
}
}
}
}
return -1;
}
int main() {
int m, n;
cin >> n >> m;
cout << solve(n, m);
}```