log P1080国王游戏

洛谷普及训练场贪心的最后一题

思想上确实是贪心但因为数据范围的问题我80%的时间都是在写高精(魔鬼)

本题的贪心策略的求解过程几乎是纯数学推导,但一旦把握了这个方向想推出来还是比较容易的,接下来只要耐心把排序和高精写好就可以了

那么来说一下推导过程:

首先是本题的无后效性:每个大臣得到的金币数并不会影响后续大臣得到的金币数,因为每位大臣得到的金币数都取决于自己右手的金币数。

确定这一点之后,不妨让我们请出队尾的两名大臣叶光迪和程驰(程驰为最后),他们左右手上的数字分别是x1,y1和x2,y2。

来分类讨论看看他们是如何走位排序来满足贪心国王的企图:

    假设前面所有大臣左手数字总和为w

1.叶光迪在程驰前面时,他得到的金币数为 w/y1 ,而程驰得到的金币数为 w*x1/y2 。因此最多金币数gold1即为两式中较大的一项

2.程驰在叶光迪前面时,同理,最多金币数gold2为 w/y2 和w*x2/y1 中较大的一项

由题意得,既然叶光迪在程驰前面,那么说明gold1一定小于gold2,不然不会这么排序

本题最难理解的地方来了:若gold1<gold2,我们就可以得到 w*x1/y2<w*x2/y1 ,进而x1y1<x2y2

为什么呢? 进行一下数学推导:1.w*x2/y1>w/y1   w*x1/y2>w/y2

                                            2.gold1和gold2不可能分别等于w/y1和w/y2(不符题意,自行证明)

                                            3.当gold1=w/y1(w/y1>w*x1/y2) w/y2<w*x2/y1 所以w*x1/y2<w*x2/yi

这样,我们很愉快地得出了贪心策略:将左右手乘积小的大臣排在前面

感谢叶光迪和程驰大臣

 1 #include<cstdio>
 2 #include<iostream>
 3 int n,l=1,a[100010],b[100010],c[100010];
 4 int g[1000010];
 5 void cheng(int x),chu(),sort(int l,int r);
 6 int main()
 7 {
 8     scanf("%d %d %d",&n,&b[0],&c[0]);
 9     for(int i=0;i<n;i++)
10     {
11         scanf("%d %d",&b[i],&c[i]);
12         a[i]=b[i]*c[i];
13     }
14     g[1]=b[0]; 
15     for(int i=1;i<n;i++) 
16     cheng(i); chu();
17     for(int i=l;i>=1;i--) printf("%d",g[i]);
18     return 0;
19 }
20 
21 void chu(){
22     for(int i=l;i>=1;i--)
23     {
24         g[i-1]+=((g[i]%c[n])*10);
25         g[i]/=c[n];
26     }
27     while(g[l]==0) l--;
28     if(l==0) printf("1
"); 
29 }
30 
31 void cheng(int x){
32     for(int i=1;i<=l;i++) 
33     g[i]*=b[x];
34     for(int i=1;i<=l;i++)
35     {
36         g[i+1]+=(g[i]/10);
37         g[i]%=10;
38     }
39     l++;
40     while(g[l]>9)
41     {
42         g[l+1]+=(g[l]/10);
43         g[l]%=10;
44         l++;
45     }
46     if(g[l]==0) l--;
47 }
48 
49 void sort(int l,int r)
50 {
51     int le=l,ri=r,mid=a[(l+r)/2];
52     while(le<=ri)
53     {
54         while(a[le]<mid) 
55         le++;
56         while(a[ri]>mid) 
57         ri--;
58         if(le<=ri)
59         {
60             int t=a[le]; 
61             a[le]=a[ri]; 
62             a[ri]=t;
63             
64             t=b[le]; 
65             b[le]=b[ri]; 
66             b[ri]=t;
67             
68             t=c[le]; 
69             c[le]=a[ri]; 
70             c[ri]=t;
71             le++; ri--;
72         }
73     }
74     if(l<ri) 
75     sort(l,ri);
76     if(le<r) 
77     sort(le,r);
78 }
原文地址:https://www.cnblogs.com/charlesss/p/10146512.html