NOIp提高组 2012国王游戏————贪心+高精度

题解:本题主要考查贪心+高精度
简要题意:有 n n n位大臣,左手右手分别写一个数,国王也写。排成一排,国王站最前面。每位大臣获得的金币数分别是:排在该大臣前面的所有人的左手上的数的乘积除以他自己右手上的数,然后向下取整得到的结果。求奖赏最多的大臣,所获奖赏尽可能的少。
1.贪心:本题的贪心很巧妙,我们可以从小规模的数据入手。
kin: n 1 , n 2 n_1,n_2 n1,n2
p1:​ x 1 , y 1 x_1,y_1 x1,y1
p2:​ x 2 , y 2 x_2,y_2 x2,y2
得出答案: a n s 1 = m a x ( n 1 ÷   y 1 , n 1 ×   x 1 ÷   y 2 ) ; ans1=max(n_1 \div\ y_1,n_1 \times\ x_1 \div\ y_2 ); ans1=max(n1÷ y1,n1× x1÷ y2);
如果我们交换p1 p2的位置
kin: n 1 , n 2 n_1,n_2 n1,n2
p2:​ x 2 , y 2 x_2,y_2 x2,y2
p1:​ x 1 , y 1 x_1,y_1 x1,y1
a n s 2 = m a x ( n 1 ÷   y 2 , n 1 ×   x 2 ÷   y 1 ) ; ans2=max(n_1 \div\ y_2,n_1 \times\ x_2 \div\ y_1 ); ans2=max(n1÷ y2,n1× x2÷ y1);
那么如果 a n s 1 ​ < a n s 2 ans1​<ans2 ans1<ans2 ​那么易得:
n 1 ×   x 2 ÷   y 1 < n 1 ×   x 1 ÷   y 2 ; n_1 \times\ x_2 \div\ y_1<n_1 \times\ x_1 \div\ y_2; n1× x2÷ y1<n1× x1÷ y2;
所以得: x 1 ×   y 1 < x 2 ×   y 2 ; x_1 \times\ y_1<x_2 \times\ y_2; x1× y1<x2× y2;
那么我们以 x i ∗ y i x_i*y_i xiyi​为关键字排序即可。
2.高精度:统计答案要写高精度。
代码如下:

#include<iostream>
#include<algorithm>
#include<cstring> 
using namespace std;
struct Node 
{
    int l;
    int r;
    long long ab;
}coin[1010];
int now[20010],sum[20010],ans[20010],add[20010];
int n;
void times(int x) //高精度加法
{
    memset(add,0,sizeof(add));
    for(int i=1;i<=ans[0];i++) 
	{
        ans[i]=ans[i]*x;
        add[i+1]+=ans[i]/10;
        ans[i]%=10;
    }
    for(int i=1;i<=ans[0]+4;i++) 
	{
        ans[i]+=add[i];
        if(ans[i]>=10) 
		{
            ans[i+1]+=ans[i]/10;
            ans[i]%=10;
        }
        if(ans[i]!=0)ans[0]=max(ans[0],i);
    }
    return ;
}
void divition(int x) //高精度除法
{
    memset(add,0,sizeof(add));
    int q=0;
    for(int i=ans[0];i>=1;i--) 
	{
        q*=10;
        q+=ans[i];
        add[i]=q/x;
        if(add[0]==0 && add[i]!=0)add[0]=i;
        q%=x; 
    }
    return ;
}
bool compare() 
{
    if(sum[0]==add[0]) 
        for(int i=add[0];i>=1;i--) 
		{
            if(add[i]>sum[i])return 1;
            if(add[i]<sum[i])return 0;
        }
    if(add[0]>sum[0])return 1;
    if(add[0]<sum[0])return 0;
}
void cp() 
{
    memset(sum,0,sizeof(sum));
    for(int i=add[0];i>=0;i--) 
	sum[i]=add[i];
    return ;
}
bool cmp(Node a,Node b) 
{
    return a.ab<b.ab;
}
int main() 
{
    cin>>n;
    for(int i=0;i<=n;i++)
    {
    	cin>>coin[i].l>>coin[i].r;
    	coin[i].ab=coin[i].l*coin[i].r;
    }
    sort(coin+1,coin+n+1,cmp);
    ans[0]=1,ans[1]=1;
    for(int i=1;i<=n;i++) 
	{
        times(coin[i-1].l);
        divition(coin[i].r);
        if(compare())cp();
    }
    for(int i=sum[0];i>=1;i--)cout<<sum[i];
    return 0;
} 
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值