ACdream之使用vector和queue进行邻接表的广搜

娜娜面对无桥无船的困境,利用智慧与策略,通过跳跃石头的方式,尝试到达湖的另一岸。本文详细介绍了如何通过广搜算法解决跳跃问题,包括输入数据解析、邻接表构建、广度优先搜索应用以及输出结果的判断与计算。通过实例演示,读者可以深入理解跳跃算法与路径规划的基本原理。

B - 娜娜梦游仙境系列——跳远女王

Time Limit:  2000/1000MS (Java/Others)     Memory Limit:  128000/64000KB (Java/Others)
Problem Description

娜娜觉得钢琴很无趣了,就抛弃了钢琴,继续往前走,前面是一片湖,娜娜想到湖的对岸,可惜娜娜找了好久都没找到小桥和小船,娜娜也发现自己不是神仙,不能像八仙过海一样。正当娜娜发愁的时候,娜娜发现湖上面有一些石头!娜娜灵机一动,发现可以沿着石头跳吖跳吖,这样一直跳下去,或许能跳到对岸!

 

娜娜把所有石头的位置都告诉你,然后娜娜能跳的最远距离也是知道的~请聪明的你告诉娜娜,她能够顺利到达对岸吗?

 

为了能够顺利的表达每个石头的位置,假设娜娜正在x轴上,表示湖的一岸,湖的另一岸是直线y=y0,湖中的石头都以有序二元组<x,y>表示,我们可以假设湖是无穷宽,两个石头的距离为几何距离,石头与岸的距离为点到直线的距离。

Input

多组数据,首先是一个正整数t(t<=20)表示数据组数

对于每组数据首先是三个整数y0(1<=y0<=1000),n(0<=n<=1000),d(0<=d<=1000),分别表示湖的另一岸的位置、石头的个数、娜娜一次最远能跳的距离。

接下来是n行,每行是两个整数x,y(0<=|x|<=1000,0<y<y0)

Output

对于每组数据,如果娜娜能够到达湖的另一岸,先输出“YES”,再输出一个整数,表示娜娜最少要跳多少次才能到达另一岸,

如果娜娜不能到达湖的另一岸,先输出“NO”,再输出一个整数,表示娜娜距离湖的另一岸最近的距离。(注意大小写)

Sample Input
2
4 3 1
0 1
0 2
0 3
6 3 2
0 1
1 2
2 3
Sample Output
YES
4
NO
3
Hint

样例一,从x轴->(0,1)->(0,2)->(0,3)->对岸,总共跳4步,输出4

样例二,从x轴->(0,1)->(1,2)->(2,3),此时距离对岸的距离为3,最大跳跃距离为2,无法到达对岸,故输出3

这题一句话不会做,参考月神代码,自己整理了一遍思路,自己敲了一下,

主要就是使用vector容器进行邻接表的储存和使用queue容器进行广搜bfs,

代码如下:

#include<iostream>
#include<cstdio>
#include<cstring>
#include<cmath>
#include<cctype>
#include<string>
#include<vector>
#include<set>
#include<map>
#include<algorithm>
#include<queue>
#define LL long long
using namespace std;
struct point
{
    int x,y;
}p[1005];
vector <int> mp[1005];
struct answer
{
    int num,step;
    answer(){}
    answer(int num,int step):num(num),step(step){}
};
int t,yo,n,d;
int ok;
bool dis(point a,point b)
{
    if(sqrt((a.x-b.x)*(a.x-b.x)+(a.y-b.y)*(a.y-b.y))<=d)
        return 1;
    return 0;
}
int vis[1005];
int bfs()
{
    ok=0;
    int mian=yo;
    queue<answer> qu;
    qu.push(answer(0,0));
    while(!qu.empty())
    {
        answer tmp=qu.front();
        qu.pop();
        mian=min(mian,yo-p[tmp.num].y);
        if(tmp.num==n+1)
        {
            ok=1;
            return tmp.step;
        }
        for(int i=0;i<mp[tmp.num].size();i++)
        {
            if(!vis[mp[tmp.num][i]])
            {
                vis[mp[tmp.num][i]]=1;
                qu.push(answer(mp[tmp.num][i],tmp.step+1));
            }
        }
    }
    return mian;
}
int main()
{
    cin>>t;
    while(t--)
    {

        for(int i=0;i<1005;i++)
            mp[i].clear();
        memset(vis,0,sizeof(vis));
        cin>>yo>>n>>d;
        for(int i=1;i<=n;i++)
            cin>>p[i].x>>p[i].y;
        if(yo<=d)
            mp[0].push_back(n+1);
        for(int i=1;i<=n;i++)
        {
            if(p[i].y<=d)
                mp[0].push_back(i);
            if(yo-p[i].y<=d)
                mp[i].push_back(n+1);
            for(int j=i+1;j<=n;j++)
                if(dis(p[i],p[j]))
                {
                    mp[i].push_back(j);
                    mp[j].push_back(i);
                }
        }
        int tt=bfs();
        if(ok)
            cout<<"YES"<<endl<<tt<<endl;
        else
            cout<<"NO"<<endl<<tt<<endl;
    }
}


 

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值