[codeforces 1369C] RationalLee 自大到小分配+自少向多分配+不定长数组的使用

Codeforces Round #651 (Div. 2)  参与排名人数14559

[codeforces 1369C]    RationalLee   自大到小分配+自少向多分配+不定长数组的使用

总目录详见https://blog.csdn.net/mrcrack/article/details/103564004

在线测评地址http://codeforces.com/contest/1369/problem/C

ProblemLangVerdictTimeMemory
C - RationalLee GNU C++17Accepted140 ms10800 KB

题目大意:给定一个数组,将其元素分配到不同的朋友手上,找到每个朋友手上元素的最大值,最小值,求和,寻找一种分配方式,让其和最大。输出这个最大和。

样例解释如下:

4 2
1 13 7 17
1 3

48
朋友1分配的元素17,最大值是17,最小值是17,和值是17+17=34
朋友2分配的元素1,13,7,最大值是13,最小值是1,和值是13+1=14
最大和值是34+14=48


6 2
10 10 10 10 11 11
3 3

42
朋友1分配的元素11,10,10,最大值是11,最小值是10,和值是11+10=21
朋友2分配的元素11,10,10,最大值是11,最小值是10,和值是11+10=21
最大和值是21+21=42


4 4
1000000000 1000000000 1000000000 1000000000
1 1 1 1

8000000000
朋友1分配的元素1000000000,最大值是1000000000,最小值是1000000000,和值是1000000000+1000000000=2000000000
朋友2分配的元素1000000000,最大值是1000000000,最小值是1000000000,和值是1000000000+1000000000=2000000000
朋友3分配的元素1000000000,最大值是1000000000,最小值是1000000000,和值是1000000000+1000000000=2000000000
朋友4分配的元素1000000000,最大值是1000000000,最小值是1000000000,和值是1000000000+1000000000=2000000000
最大和值是2000000000+2000000000+2000000000+2000000000=8000000000

赛中,第一发WA,想歪了,经过不断模拟才纠正了想歪的思路,若想看纠正过程,可看AC代码之后的内容。

基本思路:第一步,将数组元素自大到小排序,将朋友能分配到的元素个数自少到多排序。

两次分配,第一次,将数组元素自大到小,分配给每个朋友一个元素。

第二次,将剩下的数组元素自大到小,先分配给需求数量少的朋友,充分分配完后,再分配给需求逐渐增多的朋友,直至分配完成。

具体过程如下:

10 4
10 9 8 7 6 5 4 3 2 1
1 2 3 4

55

第一遍分配:
朋友1分配:10
朋友2分配:9
朋友3分配:8
朋友4分配:7

第二遍分配:
朋友1分配:10
朋友2分配:9 6
朋友3分配:8 5 4
朋友4分配:7 3 2 1


朋友1分配:10,最大值是10,最小值是10,和值是10+10=20
朋友2分配:9 6,最大值是9,最小值是6,和值是9+6=15
朋友3分配:8 5 4,最大值是8,最小值是3,和值是8+4=12
朋友4分配:7 3 2 1,最大值是7,最小值是1,和值是7+1=8
最大和值20+15+12+8=55

AC代码如下:

#include <cstdio>
#include <algorithm>
#include <vector>
#define maxn 200010
#define LL long long
using namespace std;
int a[maxn],w[maxn];
LL ans;
vector<int> q[maxn];
int cmp(int a,int b){
	return a>b;
}
void solve(){
	int n,k,i,cnt,j;
	scanf("%d%d",&n,&k);
	for(i=1;i<=n;i++)scanf("%d",&a[i]);
	for(i=1;i<=k;i++)scanf("%d",&w[i]);
	sort(a+1,a+1+n,cmp);//自大到小排序
	sort(w+1,w+1+k);//自少到多排序
	cnt=0,ans=0;
	for(i=1;i<=k;i++)q[i].clear();
	for(i=1;i<=k;i++)q[i].push_back(a[i]),w[i]--;//第一次分配
	j=k+1;
	for(i=1;i<=k;i++)//第二次分配
		while(w[i])q[i].push_back(a[j]),w[i]--,j++;
	for(i=1;i<=k;i++)
		ans+=q[i][0]+q[i][q[i].size()-1];
	printf("%lld\n",ans);
}
int main(){
	int t;
	scanf("%d",&t);
	while(t--)solve();
}

赛中,第一发WA,想歪了,经过不断模拟才纠正了想歪的思路,若想看纠正过程,可看AC代码之后的内容。

10 4
10 9 8 7 6 5 4 3 2 1
1 2 3 4

面对如上数据
朋友1分配:10,最大值是10,最小值是10,和值是10+10=20
朋友2分配:9 6,最大值是9,最小值是6,和值是9+6=15
朋友3分配:8 5 3,最大值是8,最小值是3,和值是8+3=11
朋友4分配:7 4 2 1,最大值是7,最小值是1,和值是7+1=8
最大和值20+15+11+8=54

分配显然有问题:

面对如上数据,应这样分配
朋友1分配:10,最大值是10,最小值是10,和值是10+10=20
朋友2分配:9 6,最大值是9,最小值是6,和值是9+6=15
朋友3分配:8 5 4,最大值是8,最小值是3,和值是8+4=12
朋友4分配:7 3 2 1,最大值是7,最小值是1,和值是7+1=8
最大和值20+15+12+8=55

 

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值