题目链接
Description
一天,小明需要把x只羊和y只狼运输到河对面。船可以容纳n只动物和小明。每次小明划船时,都必须至少有一只动物来陪他,不然他会感到厌倦,不安。不论是船上还是岸上,狼的数量如果超过羊,狼就会把羊吃掉。小明需要把所有动物送到对面,且没有羊被吃掉,最少需要多少次他才可以穿过这条河?
Input
有多组数据,每组第一行输入3个整数想x, y, n (0≤ x, y,n ≤ 200)
Output
如果可以把所有动物都送过河,且没有羊死亡,则输出一个整数:最少的次数。 否则输出 -1 .
Sample Input
3 3 2
33 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
这道题是一道抽象的bfs题
将河岸分成左岸和右岸
初始化:所有的狼和羊全在河的左岸。
bfs的结束条件:狼和羊全都到右岸。
bfs内部操作:在当前岸上分别从0开始枚举出船能运送的狼数和羊数 并且加上题目中所给出的限制条件 满足条件就入队。
下面附上我的代码代码中bfs函数中while循环里的一大片continue就是限制条件 我喜欢叫剪枝。
#include<cstdio>
#include<algorithm>
#include<cstring>
#include<queue>
#include<iostream>
#include<stack>
#include<map>
#include<string>
using namespace std;
struct node{
int g;
int w;
int bank;//bank为0代表在左岸 为1代表在右岸
int times;
}cur, nxt;
bool vis[205][205][2];
int sg, sw, lmt;//sg羊的总量 sw狼的总量 lmt船的运输量限制
void bfs(node t){
queue<node> q;
while(!q.empty()){
q.pop();
}
q.push(t);
vis[cur.g][cur.w][0] = true;
bool flag = 0;
while(!q.empty()){
cur = q.front();
q.pop();
if(cur.w == sw && cur.g == sg && cur.bank == 1){
flag = 1;
printf("%d\n", cur.times);
break;
}
nxt.bank = 1-cur.bank;
nxt.times = cur.times+1;
for(int i = 0; i <= cur.g; ++i){//i = goat in ship
for(int j = 0; j <= cur.w; ++j){//j = wolf in ship
if(i+j == 0) continue;
if(i+j > lmt) continue;
if(i<j && i!=0) continue;
if((cur.g-i)<(cur.w-j) && (cur.g-i) > 0) continue;
nxt.g = sg-cur.g+i;
nxt.w = sw-cur.w+j;
if(nxt.g<nxt.w && nxt.g>0) continue;
if(vis[nxt.w][nxt.g][nxt.bank]) continue;
q.push(nxt);
vis[nxt.w][nxt.g][nxt.bank] = true;
}
}
}
if(!flag){
printf("-1\n");
}
}
int main(){
while(scanf("%d%d%d", &sg, &sw, &lmt) != EOF){
memset(vis, false, sizeof(vis));//初始化vis数组
cur.g = sg;
cur.w = sw;
cur.bank = 0;
cur.times = 0;
bfs(cur);
}
return 0;
}