洛谷 P1744 采购特价商品

            洛谷 P1744 采购特价商品

题目背景

《爱与愁的故事第三弹·shopping》第一章。

题目描述

中山路店山店海,成了购物狂爱与愁大神的“不归之路”。中山路上有n(n<=100)家店,每家店的坐标均在-10000~10000之间。其中的m家店之间有通路。若有通路,则表示可以从一家店走到另一家店,通路的距离为两点间的直线距离。现在爱与愁大神要找出从一家店到另一家店之间的最短距离。你能帮爱与愁大神算出吗?

输入输出格式

输入格式:

共n+m+3行:

第1行:整数n

第2行~第n+1行:每行两个整数x和y,描述了一家店的坐标

第n+2行:整数m

第n+3行~第n+m+2行:每行描述一条通路,由两个整数i和j组成,表示第i家店和第j家店之间有通路。

第n+m+3行:两个整数s和t,分别表示原点和目标店

输出格式:

仅一行:一个实数(保留两位小数),表示从s到t的最短路径长度。

输入输出样例

输入样例#1: 复制
5
0 0
2 0
2 2
0 2
3 1
5
1 2
1 3
1 4
2 5
3 5
1 5
输出样例#1: 复制
3.41

说明

100%数据:n<=100,m<=1000

4.4 晚上,学妹问我这道题,其实是很久之前做的了,刚开始一看题目还以为是DP(背包)  hua ji

思路:根据每个点的 x,y 坐标 求出每两点间的直线距离(两点间距离公式:sqrt( ( x1-x2 ) * ( x1-x2 ) + ( y1-y2 ) * ( y1-y2 ) ) )

然后跑一遍SPFA,完事儿

/*有些地方稍微给学妹改了一下,但大体是没动的,希望学妹不要介意啊      2333*/
#include<algorithm>
#include<iostream>
#include<cstdio>
#include<cmath>
#define MAXN 100000000
using namespace std;
double a[101][3], d[1010], b[1010];
int n, m, x, y, c[1010][3], Q, W;
int main() {
    cin >> n;
    for(int i = 1; i <= n; i++)
        cin >> a[i][1] >> a[i][2];
    cin >> m;
    for(int i = 1; i <= m; i++)
        d[i] = MAXN, c[i][1] = MAXN, c[i][2] = MAXN;
    for(int i = 1; i <= m; i++) {
        cin >> x >> y, c[i][1] = x, c[i][2] = y;
        b[i] = sqrt(pow(a[x][1]-a[y][1], 2) + pow(a[x][2]-a[y][2], 2));
    }
    cin >> Q >> W;
    d[Q] = 0;
    for(int i = 1; i <= n; i++) {
        for(int j = 1; j <= m; j++) {
            if(d[c[j][1]]+b[j] < d[c[j][2]]) d[c[j][2]] = d[c[j][1]]+b[j];
            if(d[c[j][2]]+b[j] < d[c[j][1]]) d[c[j][1]] = d[c[j][2]]+b[j];
        }
    }
    printf("%.2f", d[W]);
    return 0;
}
学妹的代码

突然发现有些看不懂学妹的代码 2333 (放假回来让学妹讲讲)

#include<algorithm>
#include<cstring>
#include<utility>
#include<cstdio>
#include<cmath>
#include<queue>
#define M 10005
#define MAXN 0x7fffffff
using namespace std;
queue<int> q;
pair<int, int> pa[105];        //存边的横(first)纵(second)坐标
int n, m;
int tot;
double dis[M], cap[M];        //开double 确保精度
int to[M], net[M], head[M], vis[M];

void add(int u, int v, double w) {        //邻接链表存边,这样比用结构体存快一些,因为结构体还需要从里边调出来
    to[++tot] = v; net[tot] = head[u]; head[u] = tot; cap[tot] = w;
    to[++tot] = u; net[tot] = head[v]; head[v] = tot; cap[tot] = w;
}

void spfa(int x) {        //朴素的spfa
    for(int i = 1; i <= n; i++) dis[i] = 1.0 * MAXN, vis[i] = 0;
    dis[x] = 0.0; vis[x] = 1; q.push(x);
    while(!q.empty()) {
        int y = q.front(); q.pop(); vis[y] = 0;
        for(int i = head[y]; i; i = net[i]) {
            int t = to[i];
            if(dis[t] > dis[y] + cap[i]) {
                dis[t] = dis[y] + cap[i];
                if(!vis[t]) vis[t] = 1, q.push(t);
            }
        }
    }
}

int main() {
    scanf("%d", &n);
    for(int i = 1; i <= n; i++) scanf("%d%d", &pa[i].first, &pa[i].second);
    scanf("%d", &m);
    for(int i = 1; i <= m; i++) {
        int a, b;
        double c;
        scanf("%d%d", &a, &b);
        c = sqrt(double((pa[a].first-pa[b].first)*(pa[a].first-pa[b].first))+double((pa[a].second-pa[b].second)*(pa[a].second-pa[b].second)));        //精度很重要
        add(a, b, c);        //在两点间有通路的情况下求两点间距离、存边
    }
    int s, tmp;
    scanf("%d%d", &s, &tmp);
    spfa(s);
    printf("%.2lf",dis[tmp]);
    return 0;
}
既然看不懂学妹的,那就好好写题解吧

 

posted @ 2018-04-04 22:33  落云小师妹  阅读(175)  评论(4编辑  收藏  举报