文章标题

先贴出我错误的代码,我思路就错了,这道题明显不是0节点到1节点的距离最小,而是0到1的过程中每一步跳跃中的最大值要尽可能的小。所以解题的思路不是Dijkstra而是最小生成树。
错误代码:

#include<iostream>
#include<cstring>
#include<string>
#include<cstdio>
#include<math.h>
#include<algorithm>
#include<memory.h>
#include<vector>
#include<queue>
#include<map>
#define MAXNUM 210
#define INF 100000;
using namespace std;
int N, Point[MAXNUM][2], record[MAXNUM];
float W[MAXNUM][MAXNUM], dis[MAXNUM];
bool mark[MAXNUM];
float ComputeDis(int x, int y)
{
    float tmp;
    tmp = (Point[x][0] - Point[y][0])*(Point[x][0] - Point[y][0]) + (Point[x][1] - Point[y][1])*(Point[x][1] - Point[y][1]);
    tmp = sqrt(tmp);
    return tmp;
}
float Dijkstra()
{
    int i, j, k, t;
    float tmp;
    for (i = 0; i < N; i++)
        dis[i] = INF;
    dis[0] = 0;
    t = 0;
    for (i = 0; i < N; i++)
    {
        tmp = INF;
        for (j = 0; j < N; j++)
        {
            if (!mark[j] && tmp>dis[j])
            {
                tmp = dis[j];
                k = j;
            }
        }
        mark[k] = true;
        record[t++] = k;
        for (j = 0; j < N; j++)
        {
            if (!mark[j] && dis[j]>dis[k] + W[k][j])
            {
                dis[j] = dis[k] + W[k][j];
            }
        }
    }
    memset(mark, 0, sizeof(mark));
    tmp = INF;
    i = 1;
    while (i != 0)
    {
        for (j = 0; j < N; j++)
        {
            if (!mark[j] && dis[i] == dis[j] + W[j][i])
            {
                mark[j] = 1;
                tmp = min(tmp, W[j][i]);
                i = j;
                break;
            }
        }
    }
    return tmp;

}
int main()
{
    freopen("1.txt", "r", stdin);
    int i, j, Cases;
    float weight, ans;
    Cases = 1;
    while (scanf("%d", &N) != EOF&& N)
    {
        for (i = 0; i < N; i++)
        {
            scanf("%d%d", &Point[i][0], &Point[i][1]);
        }
        for (i = 0; i < N; i++)
        for (j = i + 1; j < N; j++)
        {
            weight = ComputeDis(i, j);
            W[i][j] = weight;
            W[j][i] = weight;
        }
        for (i = 0; i < N; i++)
            W[i][i] = 0;
        memset(mark, 0, sizeof(mark));
        printf("Scenario #%d\n", Cases++); 
        printf("Frog Distance = %.3f\n", Dijkstra());
    }
}

正确代码之Prime:
Accepted 332K 16MS

#include<iostream>
#include<cstring>
#include<string>
#include<cstdio>
#include<math.h>
#include<algorithm>
#include<memory.h>
#include<vector>
#define MAXNUM 210
#define INF 100000;
using namespace std;
int N, Point[MAXNUM][2];
float W[MAXNUM][MAXNUM];
bool mark[MAXNUM];
float ComputeDis(int x, int y)
{
    float tmp;
    tmp = (Point[x][0] - Point[y][0])*(Point[x][0] - Point[y][0]) + (Point[x][1] - Point[y][1])*(Point[x][1] - Point[y][1]);
    tmp = sqrt(tmp);
    return tmp;
}
float Prime()
{
    int i, j, k, a, b;
    float tmp, ans;
    vector<int> set;
    mark[0] = 1;
    ans = 0;
    set.push_back(0);
    for (i = 1; i < N; i++)
    {
        tmp = INF;
        for (j = 0; j < set.size(); j++)
        {
            for (k = 1; k < N; k++)
            {
                if (!mark[k] && tmp>W[set[j]][k])
                {
                    tmp = W[set[j]][k];
                    a = set[j];
                    b = k;
                }
            }
        }
        ans = max(ans, W[a][b]);
        if (b == 1)
        {
            break;
        }
        mark[b] = 1;
        set.push_back(b);
    }

    return ans;
}
int main()
{
    //freopen("1.txt", "r", stdin);
    int i, j, Cases;
    float weight, ans;
    Cases = 1;
    while (scanf("%d", &N) != EOF&& N)
    {
        for (i = 0; i < N; i++)
        {
            scanf("%d%d", &Point[i][0], &Point[i][1]);
        }
        for (i = 0; i < N; i++)
        for (j = i + 1; j < N; j++)
        {
            weight = ComputeDis(i, j);
            W[i][j] = weight;
            W[j][i] = weight;
        }
        for (i = 0; i < N; i++)
            W[i][i] = 0;
        memset(mark, 0, sizeof(mark));
        printf("Scenario #%d\n", Cases++); 
        printf("Frog Distance = %.3f\n", Prime());
        printf("\n");
    }
}

正确代码之Kruskal (union-find):
Accepted 396K 32MS

#include<iostream>
#include<cstring>
#include<string>
#include<cstdio>
#include<math.h>
#include<algorithm>
#include<memory.h>
#define MAXNUM 210
#define INF 100000;
using namespace std;
int N, Point[MAXNUM][2], Pre[MAXNUM];
bool mark[MAXNUM];
struct Edge
{
    int start, end;
    float cost;
}Path[MAXNUM*MAXNUM];
bool cmp(Edge a1, Edge a2)
{
    return a1.cost < a2.cost;
}
float ComputeDis(int x, int y)
{
    float tmp;
    tmp = (Point[x][0] - Point[y][0])*(Point[x][0] - Point[y][0]) + (Point[x][1] - Point[y][1])*(Point[x][1] - Point[y][1]);
    tmp = sqrt(tmp);
    return tmp;
}
int find(int i)
{
    while (Pre[i] != i)
        i = Pre[i];
    return i;
}
void Union(int a,int b)
{
    int x, y;
    x = find(a);
    y = find(b);
    if (x != y)
        Pre[y] = x;
}
float Kruskal(int t)
{
    int i, j, k;
    float ans = 0;
    bool Freddy, Fiona;
    Freddy = Fiona = 0;
    for (i = 0; i < t; i++)
    {
        if (find(Path[i].start) != find(Path[i].end))
        {
            Union(Path[i].start, Path[i].end);
            ans = max(ans, Path[i].cost);
            //if (Path[i].start == 0 || Path[i].end == 0)
                //Freddy = 1;
            //if (Path[i].start == 1 || Path[i].end == 1)
                //Fiona = 1;
        }
        //if (Fiona&&Freddy)
            //break;
        if (find(0) == find(1))
            break;
    }
    return ans;
}
int main()
{
    freopen("1.txt", "r", stdin);
    int i, j, t, Cases;
    float weight, ans;
    Cases = 1;
    while (scanf("%d", &N) != EOF&& N)
    {
        for (i = 0; i < N; i++)
        {
            scanf("%d%d", &Point[i][0], &Point[i][1]);
        }
        t = 0;
        for (i = 0; i < N; i++)
        for (j = i + 1; j < N; j++)
        {
            Path[t].cost = ComputeDis(i, j);
            Path[t].start = i;
            Path[t++].end = j;
        }
        sort(Path, Path + t, cmp);
        for (i = 0; i < N; i++)
            Pre[i] = i;
        memset(mark, 0, sizeof(mark));
        printf("Scenario #%d\n", Cases++); 
        printf("Frog Distance = %.3f\n", Kruskal(t));
        printf("\n");
    }
}

解释一下注释的那个地方为什么改成了find(1)==find(2),因为如果仅仅单纯看是否1和2已经在集合中了是不对的,应该以1的根节点和2的根节点是相同的,也就是他们已经属于一个大集合了为结束条件,此时所选择的边为最终的结果。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值