【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

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;
}





你可能感兴趣的:(动态规划,hackerrank)