国王游戏

恰逢 H 国国庆,国王邀请 n 位大臣来玩一个有奖游戏。首先,他让每个大臣在左、右手上面分别写下一个整数,
国王自己也在左、右手上各写一个整数。然后,让这 n 位大臣排成一排,国王站在队伍的最前面。排好队后,所
有的大臣都会获得国王奖赏的若干金币,每位大臣获得的金币数分别是:排在该大臣前面的所有人的左手上的数的
乘积除以他自己右手上的数,然后向下取整得到的结果。国王不希望某一个大臣获得特别多的奖赏,所以他想请你
帮他重新安排一下队伍的顺序,使得获得奖赏最多的大臣,所获奖赏尽可能的少。注意,国王的位置始终在队伍的
最前面。

Input

第一行包含一个整数 n,表示大臣的人数。 
第二行包含两个整数 a 和 b,之间用一个空格隔开,分别表示国王左手和右手上的整数。 
接下来 n 行,每行包含两个整数 a 和 b,之间用一个空格隔开,分别表示每个大臣左手和右手上的整数。 
1 ≤ n ≤1,000,0 < a、b < 10000

Output

输出只有一行,包含一个整数,表示重新排列后的队伍中获奖赏最多的大臣所获得的金币数。 

Sample Input

3 
1 1 
2 3 
7 4 
4 6 

Sample Output

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。


sol:贪心(交换法),本题问怎样排列大臣,使得获得奖赏最多的大臣所获得的金币最少。这是一个求最优解问题,我们想到贪心算法。贪心策略如何选择?
每次选择大臣左手上的金币与右手上的金币的乘积最小的靠近国王依次排列,排列后第n位大臣所获得的金币数即为答案。证明详情看LYD书。
所以,我们只需要对乘积进行从小到大排序,然后进行乘除计算即可。注意,由于乘积很大,所以该题要用到高精度。

 1 #include<bits/stdc++.h> 
 2 using namespace std;
 3 #define ll long long 
 4 inline int read()
 5 {
 6    int x=0,f=1;
 7    char ch=getchar();
 8    while(ch<'0'||ch>'9'){if(ch=='-') f=-1;ch=getchar();}
 9    while(ch>='0'&&ch<='9'){x=(x<<1)+(x<<3)+(ch-'0');ch=getchar();}
10    return x*f;
11 } 
12 ll n,temp,x,y,len=1;
13 ll ans[105000];
14 struct data
15 {
16    ll l,r;
17 }d[1010];
18 
19 bool comp(data a,data b)
20 {
21    return a.l*a.r<b.l*b.r;
22 }
23 
24 void multiply(int x)
25 {
26    for(int i=1;i<=len;i++)
27       ans[i]=ans[i]*d[x].l; 
28    for(int i=1;i<=len;i++)
29    {
30       if(ans[i]>=10)
31       {
32          ans[i+1]+=ans[i]/10;
33          ans[i]%=10;
34       }
35    }
36    len++;
37    while(ans[len]>=10)//处理最高位的进位 
38    {
39       ans[len+1]=ans[len]/10;
40       ans[len]=ans[len]%10;
41       len++;
42    }
43    if (ans[len]==0)
44       len--;
45 }
46 
47 void divide()
48 {
49    for(int i=len;i>=1;i--)
50    {
51       ans[i-1]+=(ans[i]%d[n].r)*10;
52       ans[i]/=d[n].r;
53    }
54    while(ans[len]==0)
55       len--;
56    if(len==0)//处理特殊情况,被除数小于除数,商为0 
57       printf("1
");
58 }
59 int main()
60 {
61    n=read();
62    x=read(),y=read();
63    ans[1]=x;//ans初始值为国王左手金币 
64    for(int i=1;i<=n;i++)
65       d[i].l=read(),d[i].r=read();
66    sort(d+1,d+1+n,comp);
67    for(int i=1;i<n;i++)//前n个大臣的左手金币积 
68       multiply(i);
69    divide();//乘积除以最后一位大臣的右手金币 
70    for(int i=len;i>=1;i--)
71       cout<<ans[i];
72    cout<<endl;
73    return 0;
74 }




原文地址:https://www.cnblogs.com/cutepota/p/12133088.html