Files
python/TangDou/CSP-J/AcWingTraining/T1/442.md
HuangHai 73b3035577 'commit'
2025-11-20 13:18:00 +08:00

102 lines
2.3 KiB
Markdown
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

## 排队接水
### 一、原题
https://www.luogu.com.cn/problem/P1190
P1190 [NOIP 2010 普及组] 接水问题
```cpp {.line-numbers}
#include <bits/stdc++.h>
using namespace std;
const int MAX_N = 10010; // 最大人数
const int MAX_M = 110; // 最大水龙头数
int n, m; // n: 同学人数, m: 水龙头数量
int w[MAX_N]; // 每位同学的接水量
int taps[MAX_M]; // 每个水龙头的当前结束时间
int main() {
cin >> n >> m;
// 模拟接水过程
for (int i = 0; i < n; i++) {
cin >> w[i];
// 找到最先结束的水龙头
int min_tap = 0;
for (int j = 1; j < m; j++)
if (taps[j] < taps[min_tap])
min_tap = j;
// 将i号同学的接水量分配给最先结束的水龙头
taps[min_tap] += w[i];
}
// 找到所有水龙头中最大的结束时间
int result = 0;
for (int i = 0; i < m; i++)
result = max(result, taps[i]);
cout << result << endl;
return 0;
}
```
### 二、变形2【一个水龙头前排队接水】
https://www.acwing.com/problem/content/description/5945/
```cpp {.line-numbers}
#include <bits/stdc++.h>
using namespace std;
const int N = 1005;
struct Node {
int num;
int sum;
} a[N];
bool cmp(Node x, Node y) {
if (x.sum == y.sum)
return x.num < y.num;
return x.sum < y.sum;
}
int main() {
int n;
cin >> n;
for (int i = 0; i < n; i++) {
cin >> a[i].sum;
a[i].num = i + 1;
}
sort(a, a + n, cmp);
double temp = 0.00;
for (int i = 0; i < n; i++) {
cout << a[i].num << " ";
temp += (n - (i + 1)) * a[i].sum;
}
cout << endl;
printf("%.2f", temp / n * 1.00);
return 0;
}
```
### 四、数学证明
首先我们要排的是所有的元素,但是为什么是从小到大呢???
排队总是象征要排序,每个元素在此序列下都要满足条件,也就是从中拿出两个相邻元素同样满足条件:
于是设:
$a_i$ 和 $b_i$且$a_i<b_i$
那么针对这两个元素就有两种排列情况
1.$a_i$排在$b_i$前面那么有总时间$t_1=a_i+a_i+b_i$.
2.$b_i$排在$a_i$前面那么有总时间$t_2=b_i+b_i+a_i$.
##于是由$a_i<b_i$得出 $t_1<t_2$—》变一下式子—》$a_i+a_i+b_i<b_i+b_i+a_i$;
再化简不等式得出$a_i<b_i$
于是得出结论**$a_i$$b_i$前面时时间为最小值**。
于是反推回总体两两相较那么越小的应该越排在前面以至于总时间越小