fzu2188 过河I BFS+剪枝

题目链接

http://acm.fzu.edu.cn/problem.php?pid=2188

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;
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值