102 lines
2.3 KiB
Markdown
102 lines
2.3 KiB
Markdown
|
||
## 排队接水
|
||
|
||
|
||
### 一、原题
|
||
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$前面时,时间为最小值**。
|
||
|
||
于是反推回总体,两两相较,那么越小的应该越排在前面,以至于总时间越小。
|