洛谷 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的最短路径长度。
输入输出样例
说明
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; }