【HackerRank】Angry Children 2 排序+动态规划

Bill Gates is on one of his philanthropic journeys to a village in Utopia. He has N packets of candies and would like to distribute one packet to each of the K children in the village (each packet may contain different number of candies). To avoid a fight between the children, he would like to pick K out of N packets such that the unfairness is minimized.

Suppose the K packets have (x1, x2, x3,….xk) candies in them, where xi denotes the number of candies in the ith packet, then we define unfairness as

image1

where |a| denotes the absolute value of a.

Input Format
The first line contains an integer N.
The second line contains an integer K.N lines follow each integer containing the candy in the ith packet.

Output Format
A single integer which will be minimum unfairness.

Constraints
2<=N<=105
2<=K<=N
0<= number of candies in each packet <=109

Sample Input #00

7
3
10
100
300
200
1000
20
30

Sample Output #00

40

Explanation #00

Bill Gates will choose packets having 10, 20 and 30 candies.So unfairness will be |10-20| + |20-30| + |10-30| = 40. It will be minimum as compared to any other distribution which can be verified .

Sample Input #01

10
4
1
2
3
4
10
20
30
40
100
200

Sample Output #01

10

Explanation #01

Bill Gates will choose 4 packets having 1,2,3 and 4 candies. So, unfairness will be |1-2| + |1-3| + |1-4| + |2-3| + |2-4| + |3-4| = 10

题目大意就是从长度为N的数组中选出K个子元素,使得相互之间的差的绝对值最小。

转自:https://www.hackerrank.com/blog/oct-2020-angry-children-ii

#include<stdio.h>
#include<stdlib.h>
#include<algorithm>
#include<assert.h>
using namespace std;
#define Max_N 100001
typedef long long int ll;
long long int sum[Max_N];
int N,K,input[Max_N];
ll min(ll a,ll b)
{
	if(a>b)    return b;
	else return a;
}
int main()
{
	int val;
	scanf("%d%d",&N,&K);
	assert(1<=N && N<=100000);
	assert(1<=K && K<=N);
	for(int i=1;i<=N;i++)
	{
		scanf("%d",&input[i]);
		assert(0<=input[i] && input[i]<=1000000000);
	}
	input[0]=0;
	sort(input+1,input+N+1);
	sum[0]=0;
	for(int i=1;i<=N;i++)    sum[i]=input[i]+sum[i-1];

	val=1-K;
	ll answer=0,compare,previous;
	for(int i=1;i<=K;i++){       //初始化前K个元素之间的绝对值差
		answer+=(ll)val*input[i];
		val+=2;
	}
	//printf("%lld is answeer\n",answer);
	previous=answer;
	for(int i=K+1;i<=N;i++){
		compare=(ll)(K-1)*input[i];
		compare=previous + (ll)(K-1)*input[i] + (ll)(K-1)*input[i-K]-(ll)2*(sum[i-1]-sum[i-K]); //从【1,2....K】递推到【2,3,...K+1】
		answer=min(answer,compare);
		previous=compare;
	}
	printf("%lld\n",answer);
	return 0;
}





评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值