poj2432环游世界

该博客讨论了一种通过广度优先搜索(BFS)算法解决旅行者如何以最少航班数环游世界的数学问题。问题涉及到在给定的农场经度和双向航班网络上找到一条路径,使得旅行者能够从起点出发,顺时针和逆时针飞行距离不同,最后回到起点。代码示例展示了如何利用C++实现BFS算法,通过判断路径旋转角度避免重复,并找出最短路径。
摘要由CSDN通过智能技术生成

问题描述:

        多年来,FJ在世界各地结交了大量的农民朋友。由于他有一段时间没有拜访来自英格兰的“Farmer Ted”和来自荷兰的“Boer Harms”,他很想去拜访他们。
        他知道他的每个世界各地的朋友所居住的农场的经度。该经度是描述农场在地球上的位置的角度(0..359 范围内的整数),我们将其视为圆形,而不是更复杂和传统的球形表示。除了明显的不连续性外,在这个圆圈上顺时针行驶时,经度会增加。
        FJ 计划乘飞机去拜访他的 N (1 <= N <= 5,000) 个朋友(他们的农场唯一编号为 1..N)。他知道连接不同农场的 M (1 <= M <= 25,000) 个双向航班的时间表。飞机总是在地球表面上以最短的路径飞行(即,在最短的圆弧上)。
        两个直接相连的农场之间总会有一条唯一的最短路径。没有一对对映农场(在圆圈上彼此完全相对)直接相连。
        每架飞机的飞行都可以被描述为在地球表面沿顺时针或逆时针方向飞行。例如,从经度 30 到经度 35 的航班将是顺时针方向的,从经度 350 到经度 10 的航班也是如此。然而,从经度 350 到经度 200 的航班遵循绕圆逆时针方向的最短路径。
        如果 FJ 可以环游世界,顺便拜访一些他的朋友,他会觉得很酷。他想知道这是否可行,如果可行,他可以乘坐的最少航班数量是多少。
        他想在他最好的朋友(下面输入中第一个列出的那个)的位置开始和结束他的旅程。为了确保他确实绕地球一圈,他想确保他顺时针行驶的距离与逆时针行驶的距离不同

问题分析:

整体的思路就是用一个二维数组来存每个点的状态包括走过来的距离,但由于状态量过多,所以用哈希算法来搞,bfs出最短路径。

输入 :

    第 1 行:两个空格分隔的整数:N 和 M
    第 2..N+1 行:第 i+1 行包含一个整数:第 i 个农场的经度。第 2 行包含他最好的朋友的农场的位置。
    第 N+2..N+M+1 行:第 i+N+1 行包含两个整数,给出由航班连接的两个农场的索引。

输出:

第 1 行:一个整数,指定 FJ 环游世界需要访问的最少航班数。每次 FJ 从一个农场移动到另一个农场都算作一次飞行。如果不可能进行这样的行程,则输出整数-1。

样本输入:

 

 代码:

#include<stdio.h>
#include<iostream>
#include<string.h>
#include<algorithm>
#include<set>
#include<vector>
using namespace std;
#define N 5001
int a[N];
vector<int> adj[N];
set<int> se[N];//判重 se[i] 标记航班到达i点所旋转的角度有哪些
struct Node
{
    int pos,x,cnt;
}que[500000];
int Bfs()              //BFS 搜索 关键在于判重
{ 
    Node now,next;
   now.pos=1;
   now.x=0;
   now.cnt=0;
   se[1].insert(0);
    int front=0,rear=0;
    int u,v,tx;
   que[rear++]=now;
   while(front<rear)
    {
       now=que[front++];
       u=now.pos;
       for(int i=0;i<adj[u].size();i++)
       {
          v=adj[u][i];
          tx=a[u]-a[v];
          if(tx>180) tx-=360;
          if(tx<-180) tx+=360;
          tx+=now.x;
          if(se[v].find(tx)==se[v].end())   //判重条件
          {
              if(v==1) return now.cnt+1;
             se[v].insert(tx);
             next.pos=v;
             next.x=tx;
             next.cnt=now.cnt+1;
             que[rear++]=next;
          }
       }
    }
    return -1;
}
int main()
{
    int n,m;   //n个城市,m条边,给定每个城市的经度,遵循最短原则,然后遍历一周回来,求最少要做多少次航班 
   while(scanf("%d%d",&n,&m)!=EOF)
    {
       for(int i=1;i<=n;i++)            //横向判重
       {
          adj[i].clear();
          se[i].clear();
          scanf("%d",&a[i]);
       }

       int u,v;
       for(int i=0;i<m;i++)              //纵向判重
       {
          scanf("%d%d",&u,&v);
          adj[u].push_back(v);
          adj[v].push_back(u);
       }
       printf("%d\n",Bfs());
    }
    return 0;
}

yjg

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值