洛谷:P5016
OJ: P4960
题目要求在已有的兵营布局和工兵数量基础上,通过向某个兵营派遣s2
个工兵,尽量平衡“龙”与“虎”双方的气势差。具体步骤如下:
n
:兵营的总数量。c[1..n]
:每个兵营中初始的工兵数量。m
:分界兵营编号,左侧属于“龙”势力,右侧属于“虎”势力,m号兵营中的工兵不属于任何一方。p1
、s1
:s1个工兵被天降到p1号兵营。s2
:需要选择一个兵营p2,将s2个工兵派往该兵营。m
的兵营,计算气势贡献为c[i] * (m - i)
,并累加得到龙方总气势。m
的兵营,计算气势贡献为c[i] * (i - m)
,并累加得到虎方总气势。m
的兵营中的工兵不计入任何一方的气势。gap = abs(lPower - rPower)
,表示当前“龙”与“虎”双方的气势差。s2
个工兵放在中立的m
号兵营,此时气势差保持不变。s2
个工兵放在i号兵营,龙方气势增加s2 * (m - i)
,计算新的气势差abs((lPower + s2 * (m - i)) - rPower)
。s2
个工兵放在i号兵营,虎方气势增加s2 * (i - m)
,计算新的气势差abs((rPower + s2 * (i - m)) - lPower)
。p2
,使得在派遣s2
个工兵后,“龙”与“虎”双方的气势差最小。代码实现:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 | /**************************************************************** * Description: 2018年普及组第二题 龙虎斗 * Author: Alex Li * Date: 2024-09-24 13:07:48 * LastEditTime: 2024-10-02 11:20:31 ****************************************************************/ #include <iostream> #include <vector> #include <cmath> #include <limits> using namespace std; #define LL long long int main(){ // 打开输入输出文件 freopen("fight.in","r",stdin); freopen("fight.out","w",stdout); int n, i, m, p1, p2; cin >> n; // 读取兵营数量 LL c[n + 1], s1, s2; // c[1..n]存储每个兵营的工兵数量,s1和s2分别是天降神兵的数量 for(i = 1; i <= n; i++){ cin >> c[i]; // 读取每个兵营的初始工兵数量 } cin >> m >> p1 >> s1 >> s2; // 读取分界兵营m,神兵出现的兵营p1,s1和s2的数量 c[p1] += s1; // 将s1个工兵添加到p1号兵营 LL lPower = 0; // 龙方总气势 for(i = 1; i < m; i++) { lPower += c[i] * (m - i); // 计算左侧(龙方)各兵营的气势贡献 } LL rPower = 0; // 虎方总气势 for(i = m + 1; i <= n; i++) { rPower += c[i] * (i - m); // 计算右侧(虎方)各兵营的气势贡献 } LL gap = abs(lPower - rPower); // 计算当前双方的气势差 p2 = m; // 默认将s2个工兵放在中立的m号兵营 // 遍历所有兵营,选择最优的p2位置 for(i = 1; i <= n; i++){ if(i < m){ // 如果选择将s2个工兵放在左侧(龙方)的某个兵营 // 计算将s2个工兵放在i号兵营后,新的气势差 LL newLPower = lPower + s2 * (m - i); LL newGap = abs(newLPower - rPower); if(newGap < gap){ gap = newGap; // 更新最小气势差 p2 = i; // 更新最佳p2位置 } } else if(i > m){ // 如果选择将s2个工兵放在右侧(虎方)的某个兵营 // 计算将s2个工兵放在i号兵营后,新的气势差 LL newRPower = rPower + (i - m) * s2; LL newGap = abs(newRPower - lPower); if(newGap < gap){ gap = newGap; // 更新最小气势差 p2 = i; // 更新最佳p2位置 } } // 如果i == m,则s2个工兵放在中立兵营,气势差保持不变,不需要更新 } cout << p2 << endl; // 输出最佳的p2位置 return 0; } |