## 排队接水 ### 一、原题 https://www.luogu.com.cn/problem/P1190 P1190 [NOIP 2010 普及组] 接水问题 ```cpp {.line-numbers} #include 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 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