http://acm.csu.edu.cn:20080/csuoj/problemset/problem?pid=2302
Description
战乱年代,平行宇宙各个世界混战,你是Pokemon世界中的战略参谋,你手下有n (保证为3的倍数)个宝可梦,第i个宝可梦的物理攻击数值为Ai,特殊攻击数值为Bi,你需要将这些宝可梦等分为三个军团,第一个军团需要去参加针对物理界面的对抗战争,战斗力估值W1为宝可梦的物理攻击数值之和;第二个军团需要去参加针对魔法界面的对抗战争,战斗力估值W2为宝可梦的特殊攻击数值之和;第三个军团需要去参加物理魔法兼备的综合界面的对抗战争,战斗力估值W3为所有土兵的物理攻击数值、特殊攻击数值之和除以2。你希望W1+W2+W3最大,这样才最有可能胜利。
Input
多组数据
第一行一个整数n,保证为3的倍数。( 3≤n≤100000 )
第二行n个整数,第i个数表示Ai。
第三行n个整数,第i个数表示Bi。( 1≤ Ai, Bi ≤1000 )
Output
一行一个数字,表示最大数值和,如果为小数请输出一位小数,若为整数,不要输出小数部分。
Sample Input
6 1 7 3 4 5 9 2 3 9 4 3 3
Sample Output
35
Hint
第一个军团:宝可梦2 ,宝可梦6 ,战斗力估值W1=7+9=16
第二个军团:宝可梦1 ,宝可梦3 ,战斗力估值W2=2+9=11
第三个军团:宝可梦4 ,宝可梦5 ,战斗力估值W3=[(4+4)+(5+3)]/2=8
16+11+8=35
Source
2019百度笔试
Author
Wells
思路:没注意到多组数据WA了……我们可以将这个问题转化一下,每一类贡献乘2,那么贡献分别为A+A,A+B,B+B,那么从第一类到最后一类每一类的差距都是定值B-A,因此我们可以求出n个物品2*A的和,然后按B-A排序,只需要令选出的+B-A和最大即可,令m=n/3,那么[m+1,2*m]取一次,[2m+1,3m]取两次即可。
#include<iostream>
#include<cstdio>
#include<stack>
#include<cmath>
#include<cstring>
#include<queue>
#include<set>
#include<algorithm>
#include<iterator>
#define INF 0x3f3f3f3f
typedef long long ll;
typedef unsigned long long ull;
using namespace std;
struct node
{
int x,y;
};
node a[100005];
ll sum=0;
int n;
bool cmp(node aa,node bb)
{
return aa.y-aa.x<bb.y-bb.x;
}
int main()
{
while(~scanf("%d",&n))
{
sum=0;
for(int i=0;i<n;i++)
{
scanf("%d",&a[i].x);
sum+=a[i].x*2;
}
for(int i=0;i<n;i++)
scanf("%d",&a[i].y);
sort(a,a+n,cmp);
int len=n/3;
for(int i=len;i<2*len;i++)
sum+=a[i].y-a[i].x;
for(int i=2*len;i<n;i++)
sum+=2*(a[i].y-a[i].x);
if(sum&1)
printf("%.1f\n",sum*1.0/2);
else
printf("%lld\n",sum/2);
}
return 0;
}