domino
Accepts: 462
Submissions: 1498
Time Limit: 2000/1000 MS (Java/Others)
Memory Limit: 131072/131072 K (Java/Others)
问题描述
小白在玩一个游戏。桌子上有n张多米诺骨牌排成一列。它有k次机会,每次可以选一个还没有倒的骨牌,向左或者向右推倒。每个骨
牌倒下的时候,若碰到了未倒下的骨牌,可以把它推倒。小白现在可以随意设置骨牌的高度,但是骨牌高度为整数,且至少为1,并且
小白希望在能够推倒所有骨牌的前提下,使所有骨牌高度的和最小。
输入描述
第一行输入一个整数T($1\leq T \leq 10$)
每组数据有两行
第一行有两个整数n和k,分别表示骨牌张数和机会次数。($2\leq k,n\leq 100000$)
第二行有n-1个整数,分别表示相邻骨牌的距离d,$1\leq d \leq 100000$
输出描述
对于每组数据,输出一行,最小的高度和
输入样例
1
4 2
2 3 4
输出样例
9
思路:
1、首先我们知道,如果两个骨牌之间间隔为d,那么如果我们将其分配高度的话,我们希望设定一个高度为d+1,另一个为1。
2、那么如果我们有三个骨牌,之间间隔从左到右为d1,d2,而且我们有一次推倒机会的话,我们希望设定一个高度为d1+1,一个高度为d2+1,最后一个为1,那么如果我们有两次推倒机会的话呢?我们就有机会使得那两个高度分别为d2+1,d1+1的骨牌其中一个高度为1,我们让他自己推倒就好,这个时候我们就能引入这个贪心的思想:选其中大的,设定为1,这样我们就能使得最终高度和最小 。
3、那么问题解决的方法就是:将给出的距离排序,去掉k-1个距离最大的那些骨牌,使其设定高度为1,其他的设定高度为di+1,最后一个也设定高度为1.
4、注意K>=n的时候,输出n
Ac代码:
#include<stdio.h>
#include<string.h>
#include<algorithm>
using namespace std;
#define ll __int64
ll a[1000000];
int main()
{
int t;
scanf("%d",&t);
while(t--)
{
ll n,k;
memset(a,0,sizeof(a));
scanf("%I64d%I64d",&n,&k);
for(int i=0;i<n-1;i++)
{
scanf("%I64d",&a[i]);
}
if(k>=n)
{
printf("%I64d\n",n);
continue;
}
ll tmp=k-1;
ll output=0;
sort(a,a+n-1);
for(int i=n-2-tmp;i>=0;i--)
{
output+=a[i]+1;
}
output+=k;
printf("%I64d\n",output);
}
}