洛谷 P2935 [USACO09JAN] Best Spot S



[USACO09JAN] 最佳牧场 S

题目链接:https://www.luogu.com.cn/problem/P2935

题目描述

贝茜,总是希望优化她的生活,她发现自己真的很喜欢访问农夫约翰的P (1 <= P <= 500)个牧场中的F (1 <= F <= P)个她最喜欢的牧场F_i。

贝茜知道她可以通过C (1 <= C <= 8,000)条双向的牛道(方便地编号为1…C)来连接各个牧场,以便在整个农场的任何牧场之间旅行。每条路径P_i都有一个时间T_i (1 <= T_i <= 892)来穿越该路径(无论哪个方向)和两个路径端点a_i和b_i (1 <= a_i <= P; 1 <= b_i <= P)。

贝茜想找到最好的牧场来睡觉,这样当她醒来时,到达她的F个最喜欢的牧场的平均时间就最小了。

举例来说,考虑一个农场的布局如下图所示,其中*'d牧场编号是最喜欢的。括号中的数字是穿越牛道的时间。


            1*--[4]--2--[2]--3
                     |       |
                    [3]     [4]
                     |       |
                     4--[3]--5--[1]---6---[6]---7--[7]--8*
                     |       |        |         |
                    [3]     [2]      [1]       [3]
                     |       |        |         |
                    13*      9--[3]--10*--[1]--11*--[3]--12*

以下表格显示了牧场4、5、6、7、9、10、11和12的潜在’最佳位置’的距离:

      * * * * * * 最喜欢的 * * * * * *
 潜在的最佳      牧场     牧场     牧场     牧场     牧场     牧场     平均
牧场              1       8      10      11      12      13        距离
------------      --      --      --      --      --      --      -----------
    4              7      16       5       6       9       3      46/6 = 7.67
    5             10      13       2       3       6       6      40/6 = 6.67
    6             11      12       1       2       5       7      38/6 = 6.33
    7             16       7       4       3       6      12      48/6 = 8.00
    9             12      14       3       4       7       8      48/6 = 8.00
   10             12      11       0       1       4       8      36/6 = 6.00 ** 最佳
   11             13      10       1       0       3       9      36/6 = 6.00
   12             16      13       4       3       0      12      48/6 = 8.00

因此,假设这些选择是最好的(一个程序必须以某种方式检查所有的选择),最好的睡觉地点是牧场10。

约翰拥有P(1<=P<=500)个牧场.贝茜特别喜欢其中的F个.所有的牧场 由C(1 < C<=8000)条双向路连接,第i路连接着ai,bi,需要Ti(1<=Ti< 892)单 位时间来通过.

作为一只总想优化自己生活方式的奶牛,贝茜喜欢自己某一天醒来,到达所有那F个她喜欢的 牧场的平均需时最小.那她前一天应该睡在哪个牧场呢?请帮助贝茜找到这个最佳牧场.

此可见,牧场10到所有贝茜喜欢的牧场的平均距离最小,为最佳牧场.

输入格式

* 第1行:三个空格分隔的整数:P、F和C

* 第2行到F+1行:第i+2行包含一个整数:F_i

* 第F+2行到C+F+1行:第i+F+1行用三个空格分隔的整数描述牛道i:a_i、b_i和T_i

输出格式

* 第1行:一行,一个整数,表示最好的牧场在哪里睡觉。如果有多个牧场是最好的,选择最小的那个。

样例 #1

样例输入 #1

13 6 15 
11 
13 
10 
12 
8 
1 
2 4 3 
7 11 3 
10 11 1 
4 13 3 
9 10 3 
2 3 2 
3 5 4 
5 9 2 
6 7 6 
5 6 1 
1 2 4 
4 5 3 
11 12 3 
6 10 1 
7 8 7

样例输出 #1

10

提示

如题目所述

如题目所述。



思路解析

F l o y d Floyd Floyd 算法将多源最短路算出多源点的最短路距离,最后加起来比较即可。


CODE

#include <iostream>
#include <vector>
#include <cstring>
#include <algorithm>
#include <queue>
#define ll long long
#define INF 0x3f3f3f3f 

using namespace std;

typedef pair<int, int> pii;

const int N = 520, M = 8010;
int d[N][N]; // 存储每个节点之间的最短距离
int n, m, k; // n是节点数,k是喜欢的节点数,m是边的数目
vector<int> love; // 存储喜欢的节点

// Floyd-Warshall算法,用于计算所有节点对之间的最短路径
void floyd(){
	for(int k = 1; k <= n; ++k)
		for(int i = 1; i <= n; ++i)
			for(int j = 1; j <= n; ++j)
				d[i][j] = min(d[i][j], 
				(d[i][k] == INF || d[k][j] == INF) ? INF : d[i][k] + d[k][j]);
}

int main(){
	cin >> n >> k >> m; // 输入节点数,喜欢的节点数,边的数目
	
	// 初始化距离矩阵
	for(int i = 1; i <= n; ++i)
		for(int j = 1; j <= n; ++j)
			d[i][j] = (i == j ? 0 : INF);
	
	// 输入喜欢的节点
	while(k--){
		int f;
		scanf("%d", &f);
		love.push_back(f); 
	}
	
	// 输入边的信息
	while(m--){
		int a, b, w;
		scanf("%d%d%d", &a, &b, &w);
		d[a][b] = d[b][a] = min(d[a][b], w);
	}
	
	// 计算所有节点对之间的最短路径
	floyd();
	
	int ans = 0, res = INF; // 初始化答案和最小平均距离
	// 遍历所有节点,找到平均距离最小的节点
	for(int i = 1; i <= n; ++i){
        int tmp = 0;
	    for(int j = 0; j < love.size(); ++j){
	        tmp += d[i][love[j]];
	    }
	    
	    if(res > tmp){
	        res = tmp;
	        ans = i;
	    }
	}
	
	cout << ans; // 输出结果
}

  • 唯一需要注意的点就是res要初始化成一个很大的数,不然会影响后续记录最小的点
  • 18
    点赞
  • 19
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
题目描述 农夫约翰一直在观察他的奶牛们。他注意到,如果在牛群中有太多的牛靠得太近,就会导致不健康的行为和情感问题。 约翰想知道他的牛群是否存在这个问题。他定义这个问题为:在一个固定长度的段上,如果有两头高度大于等于 $y$ 的奶牛之间的距离小于 $x$,则牛群中就存在一个挤得太近的情况。 约翰有 $N$ 头牛 ($1 \leq N \leq 50,000$),每头牛的高度为 $h_i$ ($1 \leq h_i \leq 1,000,000$)。他想知道是否存在一对牛,使得它们之间的距离小于 $x$,且它们的高度都大于等于 $y$。 输入格式 第一行包含三个整数 $N, L, R$,分别表示牛的数量,段长度,和问题的最大高度。 接下来 $N$ 行,每行一个整数 $h_i$,表示每头牛的高度。 输出格式 如果存在一对牛,它们之间的距离小于 $x$,且它们的高度都大于等于 $y$,则输出 $1$,否则输出 $0$。 输入样例1 4 6 4 4 4 5 7 输出样例1 1 输入样例2 5 3 3 1 5 5 5 5 输出样例2 0 提示 对于 $30\%$ 的数据,$N \leq 500$。 对于 $100\%$ 的数据,$1 \leq N \leq 50,000$,$1 \leq L \leq 1,000,000$,且 $L \leq R$。 数据范围 时间限制:1.0s,空间限制:256MB 算法1 (暴力枚举) $O(n^2)$ 首先对输入的牛的高度进行排序,之后枚举每头牛,再枚举它后面的每头牛,如果两头牛的高度均大于等于 $y$,且它们之间的距离小于 $x$,则输出 $1$。如果最后仍然没有满足件的牛,则输出 $0$。 时间复杂度 暴力枚举,时间复杂度为 $O(n^2)$,无法通过此题。 算法2 (滑动窗口) $O(n \log n)$ 为了方便后续操作,我们将所有的牛按照它们的高度从小到大排序。之后,我们维护一个长度为 $L$ 的滑动窗口,它的右端点与左端点之间的距离小于 $x$。我们从左到右扫描每头牛,将它加入滑动窗口的左端点,同时将滑动窗口右移,直到滑动窗口的右端点与左端点之间的距离小于 $x$。 在处理完一头牛之后,我们需要判断滑动窗口中是否存在一对牛,它们的高度均大于等于 $y$,且它们之间的距离小于 $x$。我们可以用双指针来实现这个操作。我们从滑动窗口的左端点开始,向右移动一个指针 $i$,同时向右移动一个指针 $j$,直到 $h_j - h_i \leq x$。在这个过程中,我们需要判断 $h_i$ 和 $h_j$ 是否均大于等于 $y$。如果存在一对牛满足件,则输出 $1$。如果最后仍然没有满足件的牛,则输出 $0$。 时间复杂度 因为需要对所有的牛进行排序,所以时间复杂度为 $O(n \log n)$。 C++ 代码 算法3 (暴力优化) $O(n \log n)$ 首先对输入的牛的高度进行排序,之后枚举每头牛。如果当前牛的高度小于 $y$,则跳过这头牛。否则,我们从它的左边和右边各扩展出一个长度为 $x$ 的区间。如果这两个区间内的牛的数量均大于等于 $2$,且这两个区间中任意两头牛的高度均大于等于 $y$,则输出 $1$。 时间复杂度 因为需要对所有的牛进行排序,所以时间复杂度为 $O(n \log n)$。 C++ 代码
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值