zoukankan      html  css  js  c++  java
  • B 娜娜梦游仙境系列——跳远女王

    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

    题意:给出一张图,起点,终点,问是否能到达终点,如果能,输出最少的步数,如果不能,输出距离终点最近的点

    解法:构图,由于只有1000个点,可以考虑邻接矩阵,两点距离小于等于d的连一条边,y<=d的点与起点连一条边(意味着可以从起点到达),y<=y0-d的点与终点连一条边(意味着可以到达终点),别忘了y0<=d的时候要给起点与终点连一条边(或者特判输出YES 1) 然后在图上跑bfs或者其余最短路算法,怎样记录不能到达的最近距离呢?当遍历到某一个点时,判断y坐标与y0的大小可以更新mindist=min(mindist,y0-y)。若最终不能到达终点,输出mindist即可。

    note:最短路忘了怎么写了,再去学,就直接用搜索了。原先用dfs超时了,后来改用额,应该是广搜把,AC了。 。。 

    1.  先判断跳跃的距离是否d>=y0,如果成立就直接输出结果。   

    2.  如果不是,就先把能和起点相连的石子用数组mark标记为1,意为第一步。  

    3.  再把该石子和前面已经输入的石子相比,把能连在一起的用二维数组map连起来。      

    4.  之后搜索就是从1开始找满足当前步数的石子,再找能够连接的石子且下一个石子的步数必须小于当前步数no+1,才能把下一步的石子标记,如果找不到后继就结束。期间每找到一步,保存最近的距离dis。

    5.  循环一遍找可以跳到终点的石子(y0-y[i]<=d),找标记不为0且最小的步数即为结果步数。如果没有满足的石子,就跳不到终点,最近距离就为dis。

     1 #include <stdio.h>
     2 #include <string.h>
     3  
     4 int y0,n,d,map[1001][1001],x[1001],y[1001],mark[1001],way,sum,der;
     5  
     6 int getDis(int i,int j)   //求两点的平方,用来和跳跃距离d*d比较
     7 {
     8     return (x[j]-x[i])*(x[j]-x[i])+(y[j]-y[i])*(y[j]-y[i]);
     9 }
    10  
    11 void go(int no)    //从步数no=1开始查找
    12 {
    13     //printf("-%d\n",no);
    14     int i,j,k=0;
    15     for(i=0;i<n;i++)
    16     {
    17         if(mark[i]==no)     //是否满足当前步数
    18         {
    19             for(j=0;j<n;j++)
    20             {
    21                 if(map[i][j]==1&&(mark[j]==0||mark[j]>no+1))  //查找能够跳到的下一个石子,且跳跃步数要为0或者大于当前步数no+1
    22                 {
    23                     if(der>y0-y[j])                  //判断离终点最近的距离
    24                         der=y0-y[j];
    25                     mark[j]=no+1;
    26                     k=1;
    27                 }
    28             }
    29         }
    30     }
    31     if(k)               //存在下一个石子可以跳跃
    32         go(no+1);
    33 }
    34  
    35 int main()
    36 {
    37     int t,i,j;
    38     while(scanf("%d",&t)!=EOF)
    39     {
    40         while(t--)
    41         {
    42             scanf("%d %d %d",&y0,&n,&d);
    43             way=0;
    44             sum=1003;
    45             der=y0;
    46             if(y0<=d)                //终点比跳跃距离近
    47             {
    48                 sum=1;
    49                 way=1;
    50             }
    51             memset(mark,0,sizeof(mark));
    52             memset(map,0,sizeof(map));
    53             for(i=0;i<n;i++)
    54             {
    55                 scanf("%d %d",&x[i],&y[i]);
    56                 if(y[i]<=d)               //起点能跳到的石子
    57                 {
    58                     if(der>y0-y[i])
    59                         der=y0-y[i];
    60                     mark[i]=1;           //标记步数为1
    61                 }
    62                 for(j=0;j<i;j++)
    63                 {
    64                     if(getDis(i,j)<=d*d)  //两石子距离小于等于d
    65                     {
    66                         map[i][j]=1;
    67                         map[j][i]=1;
    68                     }
    69                 }
    70             }
    71             if(!way)
    72             {
    73                 go(1);
    74                 for(i=0;i<n;i++)
    75                 {
    76                     if(y0-y[i]<=d&&mark[i]!=0)      //存在可以跳到的石子(mark[i]!=0),且该石子可以跳到终点
    77                     {
    78                         way=1;
    79                         if(sum>mark[i]+1)
    80                             sum=mark[i]+1;
    81                     }
    82                 }
    83             }
    84             if(way)
    85                 printf("YES\n%d\n",sum);
    86             else
    87                 printf("NO\n%d\n",der);
    88         }
    89     }
    90     return 0;
    91 }

    PS:打得自己都晕了@#@,在此感谢林班头^_^o~ 努力!

  • 相关阅读:
    网页请求过滤器Filter
    高级查询
    SQL编程
    数据库的实现
    数据库设计
    使用ADO.NET查询和操作数据
    使用ADO.NET访问数据库
    深入C#中的String类
    使用属性升级MyBank
    C#语法快速热身
  • 原文地址:https://www.cnblogs.com/weigx/p/4428938.html
Copyright © 2011-2022 走看看