题目连接:http://acm.fzu.edu.cn/problem.php?pid=2188

意思:中文题目,就是给定狼羊的数目,求最小运输量把狼和羊全部送到对岸,条件是,岸上和船上的羊不能少于狼的数目,且每次渡船至少有一只动物。无解则输出-1。

只要认真分析,还是能够想到状态转移方法的。

假设左岸分别有x,y只羊和狼,右岸分别有羊和狼m,n只,假设从左岸分别把羊狼转移p,q只到右岸,则必须满足一下条件:

x-p不为0时,x-p>=y-q;

m+p不为0时,m+p>=n+q;

p不为0时,p>=q;

这里需要注意的是,当x-p或m+q或p为0时,需要特殊处理,此时,狼可以为任意值(必须客观)不必大于羊的数目。

从右岸到左岸的思想差不多。

分析到此。

代码:

刚开始用BFS交,TLE了,然后改写双BFS,结果却是RE,仔细一看,居然是两次都交错题目了,真是汗颜啊!!!!

不过,这题用BFS和双BFS差距还是蛮大的,一个70ms+,一个达到了900ms+。

单向BFS:

#include<iostream>
#include<cstdio>
#include<sstream>
#include<cmath>
#include<cstring>
#include<algorithm>
#include<set>
#include<queue>
#include<vector>
#include<map>
#include<string>
#define LL __int64
#define INF 0xfffffffusing namespace std;struct state{int x,y;//左岸羊狼的数目int m,n;//右岸羊狼的数目int step;//转移步数
};int vis[220][220][2];//左岸状态标志,为什么是2呢?vis[x][y]有两种不同的值//可能是从右岸转移到左岸后的x,y,也可能是从右岸转移到左岸//后的x,y,这两者是不一样的
int X,Y,N;void bfs(){queue<state> Q;Q.push((state){X,Y,0,0,0});vis[X][Y][0]=vis[X][Y][1]=1;while(!Q.empty()){state tp=Q.front();if(!tp.x && !tp.y){cout<<tp.step<<endl;return;}Q.pop();if(tp.step & 1){//从右岸到左岸for(int p=0;p<=min(N,tp.m);p++)//下面需要注意的是羊为0时,狼的数目的处理for(int q=0;!p && (q<=min(tp.n,N)) || p && q<=p && (p+q)<=min(tp.m+tp.n,N);q++){if(p+q==0) continue;int tx=tp.x+p,ty=tp.y+q,tm=tp.m-p,tn=tp.n-q;//下面也得注意羊的数目为0时,狼的数目的处理if(tm<0 || tn<0 || tm && tm<tn || tx&&tx<ty) continue;if(!vis[tx][ty][1]){vis[tx][ty][1]=1;Q.push((state){tx,ty,tm,tn,tp.step+1});}}}else{//从左岸到右岸for(int p=0;p<=min(N,tp.x);p++)for(int q=0;!p && (q<=min(N,tp.y)) || p && q<=p &&(p+q)<=min(N,tp.x+tp.y);q++){if(p+q==0) continue;int tx=tp.x-p,ty=tp.y-q,tm=tp.m+p,tn=tp.n+q;if(tx<0 || ty<0 || tx && tx<ty || tm&&tm<tn) continue;if(!vis[tx][ty][0]){vis[tx][ty][0]=1;Q.push((state){tx,ty,tm,tn,tp.step+1});}}}}cout<<-1<<endl;
}int main(){
//freopen("C:\\Documents and Settings\\All Users\\桌面\\in.txt","r",stdin);while(cin>>X){cin>>Y>>N;memset(vis,0,sizeof(vis));bfs();}return 0;
}

双向BFS:

#include<iostream>
#include<cstdio>
#include<sstream>
#include<cmath>
#include<cstring>
#include<algorithm>
#include<set>
#include<queue>
#include<vector>
#include<map>
#include<string>
#define LL __int64
#define INF 0xfffffffusing namespace std;struct state{int x,y;int m,n;int step;
};int vis[220][220][2];
int vis2[220][220][2];
int X,Y,N;
//双向BFS的代码看起来比较长,但也仅仅是BFS的基础上再Ctrl+C而已
//需要两个vis数组分别表示前后的访问状态,主要是在BFS的基础上处理相遇的情况
void bfs(){queue<state> Q,QQ;Q.push((state){X,Y,0,0,0});QQ.push((state){0,0,X,Y,0});vis2[0][0][0]=vis2[0][0][1]=1;vis[X][Y][0]=vis[X][Y][1]=1;int deep=0;while(!Q.empty() || !QQ.empty()){while(!Q.empty()){state tp=Q.front();if(tp.step!=deep) break;Q.pop();if(tp.step & 1){for(int p=0;p<=min(N,tp.m);p++)for(int q=0;!p && (q<=min(tp.n,N)) || p && q<=p && (p+q)<=min(tp.m+tp.n,N);q++){if(p+q==0) continue;int tx=tp.x+p,ty=tp.y+q,tm=tp.m-p,tn=tp.n-q;if(tm<0 || tn<0 || tm && tm<tn || tx&&tx<ty) continue;if(vis2[tx][ty][0]){cout<<(deep)*2+1<<endl;return;}//相遇时两个状态必须是连贯的if(!vis[tx][ty][1]){vis[tx][ty][1]=1;Q.push((state){tx,ty,tm,tn,tp.step+1});}}}else{for(int p=0;p<=min(N,tp.x);p++)for(int q=0;!p && (q<=min(N,tp.y)) || p && q<=p &&(p+q)<=min(N,tp.x+tp.y);q++){if(p+q==0) continue;int tx=tp.x-p,ty=tp.y-q,tm=tp.m+p,tn=tp.n+q;if(tx<0 || ty<0 || tx && tx<ty || tm&&tm<tn) continue;if(vis2[tx][ty][1]){cout<<deep*2+1<<endl;return;}if(!vis[tx][ty][0]){vis[tx][ty][0]=1;Q.push((state){tx,ty,tm,tn,tp.step+1});}}}}while(!QQ.empty()){state tp=QQ.front();if(tp.step!=deep) break;QQ.pop();if(tp.step%2==0){//这里需要和上面反过来处理,可以仔细想想for(int p=0;p<=min(N,tp.m);p++)for(int q=0;!p && (q<=min(tp.n,N)) || p && q<=p && (p+q)<=min(tp.m+tp.n,N);q++){if(p+q==0) continue;int tx=tp.x+p,ty=tp.y+q,tm=tp.m-p,tn=tp.n-q;if(tm<0 || tn<0 || tm && tm<tn || tx&&tx<ty) continue;if(vis[tx][ty][1]){cout<<(1+deep)*2<<endl;return;}if(!vis2[tx][ty][0]){vis2[tx][ty][0]=1;QQ.push((state){tx,ty,tm,tn,tp.step+1});}}}else{for(int p=0;p<=min(N,tp.x);p++)for(int q=0;!p && (q<=min(N,tp.y)) || p && q<=p &&(p+q)<=min(N,tp.x+tp.y);q++){if(p+q==0) continue;int tx=tp.x-p,ty=tp.y-q,tm=tp.m+p,tn=tp.n+q;if(tx<0 || ty<0 || tx && tx<ty || tm&&tm<tn) continue;if(vis[tx][ty][0]){cout<<(deep+1)*2<<endl;return;}if(!vis2[tx][ty][1]){vis2[tx][ty][1]=1;QQ.push((state){tx,ty,tm,tn,tp.step+1});}}}}deep++;}cout<<-1<<endl;
}int main(){
//freopen("C:\\Documents and Settings\\All Users\\桌面\\in.txt","r",stdin);while(cin>>X){cin>>Y>>N;memset(vis2,0,sizeof(vis2));memset(vis,0,sizeof(vis));bfs();}return 0;
}

FZU(2188):狼羊过河问题,状态转移,BFS求解相关推荐

  1. DLS 深度受限搜索 狼羊 过河 问题 python 实现

    深度受限搜索(DLS)简单地说就是深度有限搜索(DFS)+深度限制(limit) DLS伪代码 实例:狼羊 过河 问题 3只羊和3头狼在河岸A,想要过河抵达河岸B.它们只有一艘船并且船上必须有1-2只 ...

  2. 【华为OD机试真题】羊、狼、农夫过河(狼羊过河)(c++javapython)

    狼羊过河 时间限制:1s空间限制:256MB限定语言:不限 题目描述: 一农夫带着m只羊,n只狼过河,农夫有一条可载x只狼/羊的船:农夫在时或者羊的 数量大于狼时,狼不会攻击羊:农夫在不损失羊的情况下 ...

  3. java狼追着羊跑的程序_Java编程能力强化——狼羊过河问题

    题目:有3只狼和3只羊要过河,只有一条船,一次最多只能坐两只动物并且每次必须有动物开船,如果某一边的狼的个数大于羊的个数,羊将被吃掉,编程给出解. 关于编程思路,参考:Java编程能力强化(2)--搜 ...

  4. 用C语言解决狼羊白菜过河的思路,基于visual Studio2013解决C语言竞赛题之1079狼羊过河...

        题目 解决代码及点评 /************************************************************************/ /* ...

  5. c语言编程人狼羊菜过河,基于visual Studio2013解决C语言竞赛题之1079狼羊过河

        题目 解决代码及点评 /************************************************************************/ /* ...

  6. 人,羊,狼,菜过河问题的计算机编程实现的matlab程序,人狼羊菜渡河问题(含Matlab程序)...

    <人狼羊菜渡河问题(含Matlab程序)>由会员分享,可在线阅读,更多相关<人狼羊菜渡河问题(含Matlab程序)(2页珍藏版)>请在人人文库网上搜索. 1.人.狼.羊.菜安全 ...

  7. 狼羊菜过河问题深入学习分析——Java语言描述版

    前言 这个问题的抛出,是几个星期之前的算法课程.老师分析了半天,最后的结论是:其实就是图的遍历.那时候挺懵逼的,不管是对于图,还是遍历,或者是数据结构,心里面都没有一个十足的概念,所以搁置了这么久的问 ...

  8. java狼羊草过河_狼羊菜过河问题深入学习分析——Java语言描述版

    前言 这个问题的抛出,是几个星期之前的算法课程.老师分析了半天,最后的结论是:其实就是图的遍历.那时候挺懵逼的,不管是对于图,还是遍历,或者是数据结构,心里面都没有一个十足的概念,所以搁置了这么久的问 ...

  9. 狼羊菜问题的算法思想和C++实现(二进制状态表示 递归状态转移 回溯 剪枝)

    狼羊菜问题的算法思想和C++实现 狼羊菜问题 把[狼.羊和蔬菜]这三样东西安全地送至河的对面,你能用的工具只有身边的一艘小船.已知,这艘小船很小,当你坐在里面时,其只能搭载[狼.羊和蔬菜]这三样东西中 ...

最新文章

  1. 单一docker主机网络
  2. 2018 亚太数学建模大赛B题解题思路
  3. java cloneable 用途_java中cloneable的使用
  4. camunda流程引擎如此简单(二)
  5. function “printf“ declared implicitly
  6. 思考设计模式在自助终端软件上的应用 ——Observer(观察着)模式
  7. java 开发详解_面向接口编程详解-Java篇
  8. navicat premium 连接出现的问题
  9. 主从复制中从库Last_SQL_Errno: 1062 错误
  10. 完整学习git三 查看暂存区目录树 git diff
  11. React配置代理proxy解决跨域问题
  12. 笛科思软件培训方案txwtech software training plan
  13. 从下单到享用,美团外卖背后的分布式架构设计
  14. 吴军《态度》读书笔记
  15. MySQL 查询历史sql记录
  16. WIN2012远程桌面授权过期
  17. 微信小程序-----解决swiper默认高度150px
  18. 电影之记忆1:V字仇杀队
  19. openstack neutron基本原理
  20. jQuery的简单介绍

热门文章

  1. B站小迪安全笔记第十八天-SQL注入堆叠及waf绕过注入
  2. ubuntu根目录清理
  3. 藏獒经济崩盘 为何青藏高原会有如此之多的流浪藏獒
  4. 简单三招,就能将ppt翻译成英文,快来学习
  5. java max方法_Java max()方法
  6. 生活需要仪式感—读书笔记
  7. windows 11 in virtualbox
  8. 使用高德地图自定义创建图层(svg)
  9. 我的世界服务器物品不掉落,我的世界死亡不掉落插件无法阻止世界掉落问题
  10. win10鼠标灵敏度怎么调_刺激战场:吃鸡灵敏度怎么调最科学?大神主播手把手教学诀窍!...