第一题
图标排列描述
百度应用平台上有很多有趣的应用,每个应用都由一个开发者开发,每个开发者可能开发一个或多个应用。百度的工程师们想把应用尽可能好的推荐给用户。
研究发现,同一个开发者开发的程序的图标有很大的相似性。如果把同一个开发者开发的应用放在一起,用户很快就会厌倦相似的图标,如果把这些图标穿插摆放效果就会好很多。
现在工程师想给用户推荐来自 m 个开发者的 n 个应用,在推荐的时候这些应用的图标将排成整齐的一行展示给用户,相邻两个图标之间的距离正好是 1 ,工程师们想让这些图标尽可能的穿插摆放。为了衡量穿插摆放的效果,给每个图标定义一个“分离度”,分离度的值是指当前图标和它左边最近的来自同一个开发者的图标之间的距离。如果一个图标左边没有来自同一个开发者的图标,则分离度为 0 。所有图标穿插摆放效果的值定义为所有图标的分离度之和。
已知每个开发者开发的应用个数,请帮助百度的工程师找到图标穿插摆放效果的最大值。
输入
输入的第一行包含两个整数 n 和 m ,用一个空格分隔,分别表示应用的个数和开发者的个数。
第二行包含 m 个正整数,相邻两个数之间用一个空格分隔,表示每个开发者开发的应用个数,这些整数之和必然等于 n 。
输出
输出一个整数,表示图标穿插摆放效果的最大值。
样例输入
8 3
3 3 2
样例输出
15
提示
对于 20% 的数据, n ≤ 10 ;
对于 40% 的数据, n ≤ 100 。
对于 100% 的数据, 1 ≤ m ≤ n ≤ 100,000
没想到是数学题。。。。。。。。
当时做的时候,我先一开始就是找最优的排列序列,在计算距离,现在才知道,求出最优距离是很难的。。后来又沿着这个思路,
想这题是不贪心或者是dp。。。。推了将近一个小时没推出来。。。。最后悲剧告终。。。。。。。。。。。。。。。。。
贴个别人的解题报告,分析的挺好的。。。。。。。。。。
看到有些人第一题都写了那么复杂的代码,我觉得能写那么多代码C语言应该学的不错了,可惜题目没仔细分析,
那个可以推导公式的,也有不少人推导出来了,
但是有的人都没弄明白公式怎么来的,我就讲解一下吧
从简单情况开始分析
3个图标(2A1B),可以为AAB或者ABA,显然分离度分别为1和2,
4个图标(2A2B):ABAB,ABBA,分离度都是4,
5个图标(3A2B):穷举有点多了,A多一些就先放A,只要头尾个一个A,距离相加总是4,A最大为4,
除掉头尾的A,B的距离最大为2,就是按ABABA放的,分离度为6,
这样的话是贪心算法,先考虑A最大,然后B,如果先让B最大就是BAAAB,结果也是一样,
如果都不呢,考虑ABAAB,结果还是6,其实交换第4位和的A和B,A的距离减少1,B的距离增大1,结果是一样的,
几种算法都是一样的结果,就是说贪心算法不能给出所有的最优解,但是能保证是最优解,
现在考虑10个图标(6A2B2C),分析A.....A,用ai表示第i个A所在位置,
比如ABCAAAACBA,就是a1=1,a2=4,a3=5,a4=6,a5=7,a6=10,
A产生的距离之和为(a2-a1)+(a3-a2)+(a4-a3)+(a5-a4)+(a6-a5)=a6-a1
很容易看出中间的项被抵消了,所以就只用考虑头尾,A的距离之和就是10-1=9,
然后B的距离之和是10-2-1=7,
C的距离之和是10-2-2-1=5,
就是等差数列求和,
第一个结论是只考虑头尾,
再来分析一下贪心是不是最优,找几个例子:对于ABCAAAACAB,交换的第9位和第10位,则A的距离加1,B的距离减1,结果和前面的最优解相等,
如果让B的距离最大,如BACAAAACAB交换第1位和第2位,然后交换第9位和第10位,结果也是一样,
可以归纳证明总是可以通过交换达到贪心法的结果,那么贪心法是最优的。
然后如果某个图标只要一个,就不可能摆到头和尾处,所以要除掉,不少人忽略了,
比如数据
3 3
1 1 1
分离度就是0
剩下的问题就是化简表达式了,等差数列求和公式:s=c1+c2+...+ck=k*c1+k*(k-1)*d/2,
本题中c1=n-1
设个数为1的图标总数为c,
k=m-c
d=-2,
代入上式,得s=k*(n-1)-k*(k-1)=k*(n-k)=(m-c)*(n-m-c),
这就是最终算法