fzu2188 过河I BFS+剪枝

来源:互联网 发布:规模以上 知乎 编辑:程序博客网 时间:2024/03/28 18:28

题目链接

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