国王游戏解题报告
Posted
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了国王游戏解题报告相关的知识,希望对你有一定的参考价值。
1263. [NOIP2012] 国王游戏
★★☆ 输入文件:kinggame.in
输出文件:kinggame.out
简单对比
时间限制:1 s 内存限制:128 MB
【题目描述】
恰逢 H 国国庆,国王邀请 n 位大臣来玩一个有奖游戏。首先,他让每个大臣在左、右手上面分别写下一个整数,国王自己也在左、右手上各写一个整数。然后,让这 n位大臣排成一排,国王站在队伍的最前面。排好队后,所有的大臣都会获得国王奖赏的若干金币,每位大臣获得的金币数分别是:排在该大臣前面的所有人的左手上的数的乘积除以他自己右手上的数,然后向下取整得到的结果。
国王不希望某一个大臣获得特别多的奖赏,所以他想请你帮他重新安排一下队伍的顺序,使得获得奖赏最多的大臣,所获奖赏尽可能的少。注意,国王的位置始终在队伍的最前面。
【输入格式】
第一行包含一个整数 n,表示大臣的人数。
第二行包含两个整数a和b,之间用一个空格隔开,分别表示国王左手和右手上的整数。
接下来n行,每行包含两个整数a和b,之间用一个空格隔开,分别表示每个大臣左手和右手上的整数。
【输出格式】
输出只有一行,包含一个整数,表示重新排列后的队伍中获奖赏最多的大臣所获得的金币数。
【样例输入】
3 1 1 2 3 7 4 4 6
【样例输出】
2
【输入输出样例说明】
按 1、2、3号大臣这样排列队伍,获得奖赏最多的大臣所获得金币数为 2;
按 1、3、2这样排列队伍,获得奖赏最多的大臣所获得金币数为2;
按 2、1、3这样排列队伍,获得奖赏最多的大臣所获得金币数为 2;
按 2、3、1这样排列队伍,获得奖赏最多的大臣所获得金币数为 9;
按 3、1、2这样排列队伍,获得奖赏最多的大臣所获得金币数为 2;
按 3、2、1这样排列队伍,获得奖赏最多的大臣所获得金币数为 9。
因此,奖赏最多的大臣最少获得 2 个金币,答案输出 2。
【数据范围】
对于20%的数据,有1≤ n≤ 10,0 < a、b < 8;
对于40%的数据,有1≤ n≤20,0 < a、b < 8;
对于60%的数据,有1≤ n≤100;
对于60%的数据,保证答案不超过 10^9;
对于100%的数据,有 1 ≤ n ≤1,000,0 < a、b < 10^5。
最大的最小,很容易理解为二分,但发现二分不行,于是会往贪心的方面想。
贪心策略:l*r大的排到后面。
证明:
假设两个相邻元素a,b。两手上的数字分别为la,ra,lb,rb。
那么设a,b前面所有数的l乘积为z
那么分为两种情况
1.a在b前面
ans=max(z/ra,z*la/rb)
2.b在a前面
ans=max(z/rb,z*lb/ra)
显然可以得到的是z/ra<z*lb/ra,z/rb<z*la/rb
那么当z*lb/ra>z*la/rb时,无论第一种情况谁是最大值,ans总是小于z*lb/ra的,也就是第一种情况更优,而此时lb*rb>la*ra,a在b前面,也就是l和r乘积大的放在后面。
另一种情况同理。
那么我们就可以以l*r为关键字排序了。
注意要使用高精度。
1 #include<bits/stdc++.h> 2 using namespace std; 3 struct bigint{ 4 int len,a[5005]; 5 bigint(){} 6 bigint(int x,int y){ 7 len=x; 8 a[0]=y; 9 } 10 bigint operator * (const int o)const{ 11 int last=0; 12 bigint x; 13 for(int i=0;i<len;i++){ 14 x.a[i]=a[i]*o+last; 15 last=x.a[i]/10; 16 x.a[i]%=10; 17 }x.len=len; 18 while(last){ 19 x.a[x.len++]=last%10; 20 last/=10; 21 } 22 return x; 23 } 24 bigint operator / (const int o)const{ 25 bigint x; 26 int last=0,lens=0,p[5005]; 27 for(int i=len-1;i>=0;i--){ 28 last*=10; 29 last+=a[i]; 30 p[++lens]=last/o; 31 last%=o; 32 } 33 for(int i=0;i<lens;i++)x.a[i]=p[lens-i]; 34 while(!x.a[lens-1])lens--; 35 x.len=lens; 36 return x; 37 } 38 bool operator < (const bigint o)const{ 39 if(len!=o.len)return len<o.len; 40 for(int i=len-1;i>=0;i--){ 41 if(a[i]==o.a[i])continue; 42 return a[i]<o.a[i]; 43 } 44 } 45 void out(){ 46 for(int i=len-1;i>=0;i--)printf("%d",a[i]); 47 } 48 }ans,Max; 49 struct per{ 50 int l,r; 51 void read(){ 52 scanf("%d%d",&l,&r); 53 } 54 bool operator < (const per &o)const{ 55 return l*r<o.l*o.r; 56 } 57 }p[1005]; 58 int n; 59 int main() 60 { 61 freopen("kinggame.in","r",stdin); 62 freopen("kinggame.out","w",stdout); 63 scanf("%d",&n); 64 for(int i=1;i<=n+1;i++)p[i].read(); 65 ans=bigint(1,1); 66 ans=ans*p[1].l; 67 sort(p+2,p+n+2); 68 for(int i=2;i<=n+1;i++){ 69 Max=max(ans/p[i].r,Max);//Max.out();cout<<" "; 70 // ans.out();cout<<" "<<p[i].r<<endl; 71 ans=ans*p[i].l; 72 } 73 Max.out(); 74 return 0; 75 }
以上是关于国王游戏解题报告的主要内容,如果未能解决你的问题,请参考以下文章
解题报告 smoj 2019初二创新班(2019.3.17)