Description
Input
Output
Sample Input
Sample Output
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 暴力枚举,只想到这一步,然后开始做,这道题,做了一下午,修修改改了三个多小时,样例才过去....
然后提交,wa,再想一遍思路,才发现可能一个特殊条件,加上,ac,比赛最后只有我一个ac(渣渣们比赛,大神勿喷..),但是也是比赛过后,才发现有个比这个简单的题,无语纠结中......
花了一下午,才解决了两个题目,其他的题的知识点都没接触过,两道简单题,自己也做得迷迷糊糊的,废话不说了,代码上写的够详细了.....
感觉自己的思路都混乱了,就这样过去了..赛场上都把注释看晕了,又重新补充了一下注释..........
题解:
标记数组,标记的是两种动物的数量,另外一维标记的是河岸的状态,之前有个蚂蚁回家的题目,也是三维标记了三个状态,这个比较灵活.视情况而定...
然后就是无脑的bfs 枚举了,好像还真没什么总结的........
注意题目要求,任何时候都要羊多于狼,不,还可以没有羊,也就是每次上船或者下船,都要对两个岸上(标记数组其实就记录着另外一个岸的状态)的数量进行判断,
严格执行入队前的操作,然后就等着最优解出现了,如果一直不出现,证明不存在,输出 -1....
本来想用优先队列,但是想了想,好像没什么地方需要优先,权值的累加都是平等的,没有可以优化的好像.........
然后就跑程序了...........
#include<stdio.h>
#include<string.h>
#include<queue>
using namespace std;
int v[205][205][5],x,y,n;
struct he
{
int shep,wolf,river;//shep 羊,wolf 狼,river 河岸
int cnt;//次数
}st,tp;
void bfs()
{
memset(v,0,sizeof(v));
v[x][y][0]=1;//起始状态
queue<he> q;
if(x>=y||x==0)//如果羊不比狼少,或者没有羊
{
st.shep=x;st.wolf=y;
st.river=0;st.cnt=0;
q.push(st);
}
while(!q.empty())
{
st=q.front();q.pop();//取一个队里的状态
if(st.river==1&&st.shep==x&&st.wolf==y)//如果全部到了另外一个河岸
{
printf("%d\n",st.cnt);
return;
}
for(int i=0;i<=st.shep;++i)//把所有的状态全部枚举一遍,羊上船的数量
{
for(int j=0;j<=st.wolf;++j)//改变的狼的数量,上船
{
if(!(i+j!=0&&i+j<=n)||(i<j&&i!=0))
//每次船上只能有 1-n 个动物,并且 羊>=狼或者没羊
{
continue;
}
if(st.shep-i<st.wolf-j&&st.shep-i!=0)
//上船后,船所在岸的要满足 羊>=狼或者没羊
{
continue;
}
int ts=x-st.shep+i;//另外一个岸上的羊的数量
int tw=y-st.wolf+j;//另外一个岸上的狼的数量
int tr=!st.river;
if(ts<tw&&ts!=0)//到了另外一个岸上的也要满足
{
continue;
}
if(!v[ts][tw][tr])//状态未出现过....
{
tp.shep=ts;tp.wolf=tw;//
tp.river=tr;tp.cnt=st.cnt+1; //
q.push(tp);//符合条件入队
v[ts][tw][tr]=1;//标记
}
}
}
}
printf("-1\n");//队空则证明不存在方案
}
int main()
{
while(~scanf("%d%d%d",&x,&y,&n))
{
bfs();//搜索
}
return 0;
}
刚刚发现,好像羊的英文单词都写错了................晕死了....