党(雾) 神奇的模拟赛 贪心
来源:互联网 发布:火柴人动画软件 编辑:程序博客网 时间:2024/06/05 18:08
问题描述
你现在希望组建一支足球队,一支足球队一般来说由11人组成。这11人有四种不同的职业:守门员、后卫、中锋、前锋组成。你在组队的时候必须满足以下规则:
1.足球队恰好由11人组成。
2.11人中恰好有一名守门员,3-5 名后卫,2-5 名中锋,1-3 名前锋。
3.你需要从这11人中选出一名队长。
4.你这个足球队的价值是11人的价值之和再加上队长的价值,也就是说队长的价值会被计算两次。
5.你这个足球队的花费是11人的花费之和,你的花费之和不能超过给定的上限。
现在告诉你球员的总数,每个球员的职业、价值、花费,以及花费的上限,你希望在满足要求的情况下,达到以下目标:
1.最大化队伍的价值。
2.在最大化队伍的价值的情况下,最小化队伍的花费。
你的任务是输出这三个值:价值、花费、方案数。
输入格式
第一行一个正整数N,代表可选的球员个数。
接下来N行,每行描述一个球员的信息。每行开始是一个字符串,可能的字符串有 Goalkeeper、Defender、Midfielder、Forward,分别代表该球员的职业是守门员、后卫、中锋、前锋。接下来两个数V,C,分别代表该球员的价值和花费。
最后一行一个整数,代表花费的上限。
数据保证一定存在一种解。
输出格式
一行三个整数,分表代表最大价值、最小花费和方案数。如果方案数超过了10^9,则直接输出10^9。
分析
其实题目描述和数据不符。对于100%的数据,费用上限都不必考虑。所以我们可以用贪心写。(数据水~~)
首先,可以枚举阵容的所有可能人数分配,对于每种位置,注定要选择价值最大,花费最小的前几个人。所以对于不同种类的球员,分别按照价值降序,花费升序排序后直接取前若干人即可。然后问题只剩下了种类。不难发现,某一阵容要做等价替换,只可能替换当前阵容中价值最小,花费最大的人。记与价值最小,花费最大的人相同的人共有n人,其中需要选择m人,则该阵容的方案总数为:
代码
#include<iostream>#include<cstring>#include<cstdio>#include<cmath>#include<string>#include<algorithm>using namespace std;struct arr{ int val,coat;}g[501],d[501],m[501],f[501];int gn=0,dn=0,mn=0,fn=0;int n;long long val,coat,num;inline bool cmp(arr x,arr y){ if (x.val>y.val) return 1; if (x.val<y.val) return 0; if (x.coat<y.coat) return 1; return 0;}long long C(int n,int m){ long long ans=1; for(int i=n;i>=n-m+1;i--) ans*=i; for(int i=m;i>0;i--) ans/=i; return ans;}int count(arr G[501],int stp,int endp){ int bef=0,aft=0; for (int i=stp;i>0;i--) if ((G[i].val==G[stp].val)&&(G[i].coat==G[stp].coat)) bef++; else break; for (int i=stp;i<=endp;i++) if ((G[i].val==G[stp].val)&&(G[i].coat==G[stp].coat)) aft++; else break; return C(bef+aft-1,bef);}void mmm(int gm,int dm,int mm,int fm){ int maxg=0,maxd=0,maxm=0,maxf=0; int ming=0,mind=0,minm=0,minf=0; for (int i=1;i<=gm;i++) { maxg+=g[i].val; ming+=g[i].coat; } for (int i=1;i<=dm;i++) { maxd+=d[i].val; mind+=d[i].coat; } for (int i=1;i<=mm;i++) { maxm+=m[i].val; minm+=m[i].coat; } for (int i=1;i<=fm;i++) { maxf+=f[i].val; minf+=f[i].coat; } int tot1=maxg+maxd+maxm+maxf; int tot2=ming+mind+minm+minf; tot1+=max(g[1].val,max(d[1].val,max(m[1].val,f[1].val))); int count1=count(g,gm,gn)*count(d,dm,dn)*count(m,mm,mn)*count(f,fm,fn); if ((val<tot1)||((val==tot1)&&(coat>tot2))) { val=tot1; coat=tot2; num=count1; } else if((val==tot1)&&(coat==tot2)) { num+=count(g,gm,gn)*count(d,dm,dn)*count(m,mm,mn)*count(f,fm,fn); }}int main(){ freopen("wosa.in","r",stdin); freopen("wosa.out","w",stdout); scanf("%d",&n); string str; for(int i=1;i<=n;i++) { int a,b; cin>>str>>a>>b; if(str=="Goalkeeper") g[++gn]=(arr){a,b}; if(str=="Defender") d[++dn]=(arr){a,b}; if(str=="Midfielder") m[++mn]=(arr){a,b}; if(str=="Forward") f[++fn]=(arr){a,b}; } sort(g+1,g+gn+1,cmp); sort(d+1,d+dn+1,cmp); sort(m+1,m+mn+1,cmp); sort(f+1,f+fn+1,cmp); coat=100000000; for (int i=3;i<=min(dn,5);i++) for (int j=2;j<=min(5,mn);j++) for (int k=1;k<=min(3,fn);k++) if (i+j+k==10) mmm(1,i,j,k); cout<<val<<" "<<coat<<" "<<min(num,1000000000ll); return 0; fclose(stdin); fclose(stdout);}
- 党(雾) 神奇的模拟赛 贪心
- 神奇的贪心 + DP
- [26] Vijos P1978 神奇的幻方(模拟)
- zzulioj--1828-- 贪心的小猫咪(贪心模拟)
- [BZOJ2426][HAOI2010] 工厂选址 (神奇的贪心)
- 【贪心】[NOIP模拟赛]奇怪的队列
- #NOIP模拟赛#保证的利润(贪心 模拟)
- [BZOJ3790]神奇项链(manacher+贪心)
- BZOJ 3790 神奇项链 (Manacher 贪心)
- 机房练习赛kun (贪心 模拟)
- [考试] [NOIP模拟] [2017-11-04~05] 神奇的模拟赛
- hdu 5402 一道神奇的模拟题
- 【2015.12NOIPtj模拟】神奇的项链(fett)
- 【HNOI2016模拟4.1】神奇的字符串
- 【GDOI2018模拟8.14】神奇的矩阵
- 【JZOJ5270】【GDOI2018模拟8.14】神奇的矩阵
- 【GDOI2018模拟8.14】神奇的救火现场
- Loi 模拟赛之压轴出场的互测终曲|(*_-) 模拟+模拟+贪心+bfs+图论+数论
- ListView的一些属性
- 如何快速的开发一个完整的iOS直播app(播放篇)
- <Mooc C++ 教程作业>去除字符串首尾多余的空格
- Magent搭建Memcached集群
- Css rem和px
- 党(雾) 神奇的模拟赛 贪心
- Qt问答
- 在线/不重启/不暂停的对Java应用进行Debug,通过程序打断点并输出断点信息
- ffmpeg ffplay rtp推流命令和sdp格式
- ubuntu14.04 ssh允许root用户远程登录
- 当虚拟现实撞上高考
- 带你走进脚本世界,ijkplayer之【init-ios.sh】脚本分析
- http协议
- 以线性调频脉冲(LFM)谈采样定理