POJ 最短路径

这两天做了六道最短路径的问题,分别用了Dijkstra算法、SPFA算法和Floyd算法,甚至还有一道题用并查集做的也A了,感觉对短路径已经学得很不错了。

poj1860,poj3259,poj1062,poj2253,poj1125,poj2240

POj2253,Dijkstra和并查集都可以。

Dijkstra算法改变一下dis数组存的内容,计算方式也要相应的变一下。

Dijkstra算法AC代码:

#include <iostream>
#include <cstdio>
#include <cstring>
#include <vector>
#include <queue>
#include <algorithm>
#include <cmath>

using namespace std;

const double INF = 100000000;
const int maxn = 210;
double dis[maxn],g[maxn][maxn],N;
bool v[maxn];
int m,n;
vector<pair<int,int> > a;
double dist(pair<int,int> a,pair<int,int> b)
{
    return sqrt((double)(a.first-b.first)*(a.first-b.first) +(a.second-b.second)*(a.second-b.second));
}


void dijkstra(){
    for (int i = 1;i<=N ;i++ )dis[i] = INF;
    dis[1] = 0;
    memset(v,0,sizeof v);
    for (int i = 1;i<=N ;i++ )
    {
        int mark = -1,mindis = INF;
        for(int j = 1;j<=N;j++)
            if(!v[j] && dis[j]<mindis){
                mindis=dis[j];
                mark = j;
            }
        if(mark == -1)
            return ;
        v[mark] = 1;
        for(int j=1;j<=N;j++)
            if(!v[j])
                dis[j] = min(dis[j],max(dis[mark],g[mark][j]));
    }
}

void slove()
{
    int x,y;
    a.clear();
    for (int i = 1;i<=n ;i++ )
    {
        scanf("%d%d",&x,&y);
        a.push_back(make_pair(x,y));
    }
    for(int i=1;i<=n;i++)
        for(int j=1;j<=n;j++)
            g[i][j] = g[j][i] = dist(a[i-1],a[j-1]);
    N = n;
    dijkstra();
    printf("%.3f\n\n",dis[2]);
}

int main()
{
#ifdef ARTHUR_YANG
freopen("in.txt","r",stdin);
#endif // ARTHUR_YANG
    int t=1;
    while(~scanf("%d",&n) && n)
    {
        printf("Scenario #%d\nFrog Distance = ",t++);
        slove();
    }
}

并查集的话就是将n个点的所有边存到一个结构体中,按距离从小到大排序。对于每个边将边相连的两点用并查集连起来,并判断1点和2点是否已经相连,若没有则继续加边;若已经相连则最后连的边的距离就是最小的最长距离。

由于要对所有边进行排序,时间复杂度为O(n^2logn),相比Dijkstra的O(n^2)要大一些,但在POJ上时间都是16MS。

并查集AC代码如下:

#include <iostream>
#include <cstdio>
#include <cstring>
#include <vector>
#include <queue>
#include <algorithm>
#include <cmath>

using namespace std;
int n;
struct k
{
    int a,b;
    double dist;
    friend bool operator<(k a,k b)
    {
        return a.dist<b.dist;
    }
}g[44444];

struct DisjointSet{
    vector<int> father,rank;
    DisjointSet(int n) : father(n),rank(n){
        for(int i =0;i<n;i++)
            father[i] = i;
    }
    int find(int v)
    {
        return father[v] = father[v]==v ? v: find(father[v]);
    }
    void merge(int x,int y)
    {
        int a = find(x),b = find(y);
        if(rank[a]<rank[b])
            father[a] = b;
        else
        {
            father[b] = a;
            if(rank[b] == rank[a])
                rank[a] ++;
        }
    }
};

int num;
vector<pair<int,int> > a;

double dist(pair<int,int> a,pair<int,int> b)
{
    return sqrt((double)(a.first-b.first)*(a.first-b.first) +(a.second-b.second)*(a.second-b.second));
}

void slove()
{
    int x,y;
    a.clear();
    num = 0;
    for (int i = 1;i<=n ;i++ )
    {
        scanf("%d%d",&x,&y);
        a.push_back(make_pair(x,y));
    }
    for(int i=1;i<=n;i++)
        for(int j=1;j<=n;j++)
        {
            if(i==j) continue;
            g[num].a = i;
            g[num].b = j;
            g[num++].dist = dist(a[i-1],a[j-1]);
        }
    sort(g,g+num);
    DisjointSet di(n+1);
    for (int i=0;i<num ;i++ )
    {
         di.merge(g[i].a,g[i].b);
         if(di.find(1) == di.find(2))
         {
             printf("%.3f\n\n",g[i].dist);
             return ;
         }
    }
}

int main()
{
#ifdef ARTHUR_YANG
freopen("in.txt","r",stdin);
#endif // ARTHUR_YANG
    int t=1;
    while(~scanf("%d",&n) && n)
    {
        printf("Scenario #%d\nFrog Distance = ",t++);
        slove();
    }
}


  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
POJ2251是一个经典的题目,也被称为"水仙花的谜题"。该题目要求在一个三维的迷宫中找到从起点到终点的最短路径。 在这个题目中,迷宫由一个3D的数组表示,每个位置上的值代表了该位置的状态。其中,0表示可以通过的路径,1表示墙壁,2表示起点,3表示终点。你需要编写一个程序来找到从起点到终点的最短路径,并输出路径的长度。 解决这个问题的一种常见方法是使用广度优先搜索(BFS)算法。BFS算法可以从起点开始,逐层遍历迷宫中的位置,直到找到终点或者遍历完所有可达位置。在遍历过程中,你需要记录每个位置的距离和路径信息,以便找到最短路径。 以下是解决该问题的大致思路: 1. 定义一个队列,将起点加入队列,并标记起点已访问。 2. 使用循环来遍历队列中的元素,直到队列为空。 3. 在循环中,取出队列中的元素,并获取其相邻可达位置。 4. 对于每个相邻位置,判断是否为终点,如果是则输出最短路径长度并结束程序。 5. 如果不是终点,则判断该位置是否为可通过的路径,并且未被访问过。如果满足条件,则将该位置加入队列,并更新距离和路径信息。 6. 重复步骤2-5,直到找到终点或者遍历完所有可达位置。 这只是一个简单的介绍,实际解决该问题还需要考虑一些细节,比如如何表示迷宫、如何判断位置的合法性等。你可以在编写代码时参考相关的算法和数据结构知识。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值