题目描述
轩轩和开开正在玩一款叫《***》的游戏,游戏的棋盘是一条线段,线段上有n个兵营(自左至右编号1~n),相邻编号的兵营之间相隔1厘米,即棋盘为长度为n-1厘米的线段。i号兵营里有ci位工兵。
下面图1为n = 6的示例:
轩轩在左侧,代表“龙”;凯凯在右侧,代表“虎”。 他们以 m 号兵营作为分界, 靠左的工兵属于龙势力,靠右的工兵属于虎势力,而第 𝐦 号兵营中的工兵很纠结,他 们不属于任何一方。
一个兵营的气势为:该兵营中的工兵数 × 该兵营到 m 号兵营的距离;参与游戏 一方的势力定义为:属于这一方所有兵营的气势之和。
下面图 2 为 n = 6, m = 4 的示例,其中红色为龙方,黄色为虎方:
游戏过程中,某一刻天降神兵,共有 s1 位工兵突然出现在了p1号兵营。作为轩轩和凯凯的朋友,你知道如果龙虎双方气势差距太悬殊,轩轩和凯凯就不愿意继续玩下去了。为了让游戏继续,你需要选择一个兵营 p2,并将你手里的 s2位工兵全部派往 兵营p2,使得双方气势差距尽可能小。
注意:你手中的工兵落在哪个兵营,就和该兵营中其他工兵有相同的势力归属(如果落在 m 号兵营,则不属于任何势力)。
输入描述:
输入文件的第一行包含一个正整数 n,代表兵营的数量。
接下来的一行包含 n 个正整数,相邻两数之间以一个空格分隔,第 i 个正整数代表编号为 i 的兵营中起始时的工兵数量 。接下来的一行包含四个正整数,相邻两数间以一个空格分隔,分别代表 。
输出描述:
输出文件有一行,包含一个正整数,即 ,表示你选择的兵营编号。如果存在多个编号同时满足最优,取最小的编号。
示例1
输入
6
2 3 2 3 2 3
4 6 5 2
输出
2
说明
见问题描述中的图 2。
双方以 m=4 号兵营分界,有 S1 =5 位工兵突然出现在 P1 =6 号兵营。龙方的气势为:2 × (4 − 1) + 3 × (4 − 2) + 2 × (4 − 3) = 14虎方的气势为:此时双方气势相等。
当你将手中的 𝑠2 = 2 位工兵派往 P2 = 2 号兵营时,龙方的气势变为:
2 × (5 − 4) + (3 + 5) × (6 − 4) = 18 14 + 2 × (4 − 2) = 18
示例2
输入
6
1 1 1 1 1 16
5 4 1 1
输出
1
说明
双方以 𝑚=5 号兵营分界,有 𝑠1 =1 位工兵突然出现在 P1 =4 号兵营。 龙方的气势为:1 × (5 − 1) + 1 × (5 − 2) + 1 × (5 − 3) + (1 + 1) × (5 − 4) = 11
虎方的气势为:
16 × (6 − 5) = 16
当你将手中的 S2 = 1 位工兵派往 P2 = 1 号兵营时,龙方的气势变为:11 + 1 × (5 − 1) = 15
此时可以使双方气势的差距最小。
解答
没什么算法,只是个模拟而已
但是比较复杂一些,所以让人感觉比去年难一点
现在来分析主要程序思路:
输入兵营总数、兵营人数、以m分界。
然后输入s1个兵到了p1兵营。 最终我们要求的是把s2个兵放到哪个兵营使龙虎双方气势差距最小。
第一要把每个兵营的气势算出来,并且加到它所属的阵营里(<m是龙,>m是虎,属于m不是龙也不是虎)
然后就是考虑天降神兵了,它们到达的兵营所属阵营判断条件和上面一样
最后我们一个一个考虑把手中p2个兵放到哪个兵营最好。
#include<iostream> #include<cmath>//fabs()函数调动cmath using namespace std; long long c[100001][2];//大家能看到兵营总数10^5,工兵数10^9, //所以乘起来必须开longlong。否则60分。Pascal要开int64 int main() { long long n,m,p1,s1,s2,dragon=0,tiger=0,minn=1; //n,m,p1,s1,s2和题目中定义都一样 //dragon是龙方总气势,tiger是虎方总气势, //minn是指将s2个兵放到第minn个兵营双方气势差距最小 cin>>n; for(int i=1; i<=n; i++) cin>>c[i][0]; cin>>m>>p1>>s1>>s2; for(int i=1; i<=n; i++) { if(i<m) dragon+=c[i][0]*(m-i); else tiger+=c[i][0]*(i-m); }//这里计算了每个兵营的气势,并把它加到了所属阵营 //值得一提的是:当判断到m阵营时我将它加到了虎方 //其实加到龙方也可以,都是+0,因为(m-m)一定是0 if(p1<m) dragon+=s1*(m-p1); else tiger+=s1*(p1-m); //这里判断天降神兵后的双方气势,不用特别在意m for(int i=1; i<=n; i++) { if(i<m) c[i][1]=fabs((dragon+s2*(m-i))-tiger); else c[i][1]=fabs((tiger+s2*(i-m))-dragon); //用c[i][1]存储了如果把s2个兵放到i号兵营时双方气势差距 //fabs()避免了存储负数,以便后面查找差距最小值 //如果去掉fabs(),最小值可能会是负数,程序就错误了 } for(int i=2; i<=n; i++) if(c[minn][1]>c[i][1]) minn=i; //这个循环就是统计把s2个兵放到哪个兵营双方气势差距最小 //结果用上面提到过的minn存储 cout<<minn<<endl; return 0; //愉快的结束了 }
来源:hxwht