Files
python/TangDou/CSP-J/AcWingTraining/T1/442.md
HuangHai 573c77674e 'commit'
2025-10-05 18:33:03 +08:00

2.4 KiB
Raw Blame History

排队接水

一、数学证明

首先我们要排的是所有的元素,但是为什么是从小到大呢???

排队总是象征要排序,每个元素在此序列下都要满足条件,也就是从中拿出两个相邻元素同样满足条件:

于是设:

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$前面时,时间为最小值

于是反推回总体,两两相较,那么越小的应该越排在前面,以至于总时间越小。

二、代码

#include <bits/stdc++.h>

using namespace std;
const int N = 10010, M = 200;
int n, m;
int w[N];
int q[M];

int main() {
  cin >> n >> m;
  for (int i = 0; i < n; i++)
    cin >> w[i];

  for (int i = 0; i < n; i++) {
    // 找出最小值
    int t = 0;
    for (int j = 0; j < m; j++) {
      if (q[j] < q[t])
        t = j;
    }
    // 将i号同学安排到第t个位置上
    q[t] += w[i];
  }
  int res = 0;
  for (int i = 0; i < m; i++)
    res = max(res, q[i]); // 找出最大值就是答案
  cout << res << endl;
  return 0;
}

三、变形

【题目描述】 有$n$个人在一个水龙头前排队接水,假如每个人接水的时间为$T_i$,请编程找出这$n$个人排队的一种顺序,使得$n$个人的平均等待时间最小。

【输入】 共两行,第一行为$n(1≤n≤1000)$;第二行分别表示第$1$个人到第$n$个人每人的接水时间$T_1T_2T_n$,每个数据之间有$1$个空格。

【输出】 有两行,第一行为一种排队顺序,即$1$到$n$的一种排列;第二行为这种排列方案下的平均等待时间(输出结果精确到小数点后两位)。

【输入样例】

10							
56 12 1 99 1000 234 33 55 99 812

【输出样例】

3 2 7 8 1 4 9 6 10 5
291.90
http://ybt.ssoier.cn:8088/problem_show.php?pid=1319
#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) {
    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;
}