1. 程式人生 > >洛谷 P1744 采購特價商品

洛谷 P1744 采購特價商品

gpo 鏈表 情況 分享 AD clas radi namespace 題目

            洛谷 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;
}
既然看不懂學妹的,那就好好寫題解吧

洛谷 P1744 采購特價商品