YbtOJ 贪心算法课堂过关 例4 国王游戏【贪心】
发布日期:2021-05-07 13:09:43 浏览次数:13 分类:原创文章

本文共 2502 字,大约阅读时间需要 8 分钟。

在这里插入图片描述


思路

这道题其实主要的难点是如何排序
排序之后贪心就非常简单了。

考虑
s i = ∏ j = 0 i a j s_i=\prod\limits_{j=0}^{i}a_j si=j=0iaj

首先考虑交换前,第 i i i 个上的值是 s i − 1 b i \frac {s_{i-1}}{b_i} bisi1,第 i + 1 i+1 i+1个 是 s i − 1 × a i b i + 1 \frac {s_{i-1}\times a_i}{b_{i+1}} bi+1si1×ai
a n s 1 = max ⁡ ( s i − 1 b i , s i − 1 × a i b i + 1 ) ans_1=\max(\frac {s_{i-1}}{b_i},\frac {s_{i-1}\times a_i}{b_{i+1}}) ans1=max(bisi1,bi+1si1×ai)

交换后 i i i 的位置就变成了 i + 1 i+1 i+1 i + 1 i+1 i+1 的位置就变成了 i i i
值分别为 s i − 1 b i + 1 \frac {s_{i-1}}{b_{i+1}} bi+1si1 s i − 1 × a i + 1 b i \frac {s_{i-1}\times a_{i+1}}{b_i} bisi1×ai+1
a n s 2 = max ⁡ ( s i − 1 b i + 1 , s i − 1 × a i + 1 b i ) ans_2=\max(\frac {s_{i-1}}{b_{i+1}},\frac {s_{i-1}\times a_{i+1}}{b_i}) ans2=max(bi+1si1,bisi1×ai+1)

显然 s i − 1 b i < s i − 1 × a i + 1 b i \frac {s_{i-1}}{b_i} < \frac {s_{i-1}\times a_{i+1}}{b_i} bisi1<bisi1×ai+1
并且 s i − 1 b i + 1 < s i − 1 × a i b i + 1 \frac {s_{i-1}}{b_{i+1}} <\frac {s_{i-1}\times a_i}{b_{i+1}} bi+1si1<bi+1si1×ai
如果 a n s 1 < a n s 2 ans_1<ans_2 ans1<ans2
那么 s i − 1 × a i b i + 1 < s i − 1 × a i + 1 b i ) \frac {s_{i-1}\times a_i}{b_{i+1}}<\frac {s_{i-1}\times a_{i+1}}{b_i}) bi+1si1×ai<bisi1×ai+1)
通过化简,得:
a i ⋅ b i < a i + 1 ⋅ b i + 1 a_i\cdot b_i<a_{i+1}\cdot b_{i+1} aibi<ai+1bi+1
由此可见,对 a ∗ b a*b ab 进行关键字排序就可以了。
这题还需要高精度!!!

C o d e Code Code

#include<algorithm>#include<iostream>#include<cstring>#include<cstdio>#include<cmath>using namespace std;long long ff[10100],f[10100],ans[10100];long long n,js=1;struct node{   	long long x,y;}a[1000010];bool cmp(const node&d,const node&dd){   	return d.x*d.y<dd.x*dd.y;}void gjc(int x){   	int jw=0;	for(int i=1; i<=10000; i++)	 {   	 	f[i]=f[i]*x+jw;	 	jw=f[i]/10;	 	f[i]%=10;	 }}void gju(int x){   	int j=10000,jw=0;	while(f[j]==0)	  j--;	for(int i=j; i>=1; i--)	 {   	 	ff[i]=(f[i]+jw*10);	 	jw=ff[i]%x;	 	ff[i]/=x;	 }}void gjbj(){   	int j=10000;	while(ans[j]==0)	   j--;	int jj=10000;	while(ff[jj]==0)	   jj--;	if(jj>j)	 for(int i=1; i<=jj; i++)	    ans[i]=ff[i];	else if(jj==j)	 for(int i=jj; i>=1; i--)      if(ans[i]<ff[i])       {          	 for(int i=1; i<=jj; i++)	        ans[i]=ff[i];	     break;	   }	  else if(ans[i]>ff[i])	     break;    memset(ff,0,sizeof(ff));}int main(){   	cin>>n;	for(int i=1; i<=n+1; i++)	   scanf("%lld%lld",&a[i].x,&a[i].y);	sort(a+2,a+2+n,cmp);	f[1]=1;	for(int i=2; i<=n+1; i++)	 {   	   gjc(a[i-1].x);	   gju(a[i].y);	   gjbj();	 }	int j=10000;	while(ans[j]==0)	   j--;	for(int i=j; i>=1; i--)	   cout<<ans[i];	return 0;}
上一篇:YbtOJ 二分算法课堂过关 例1 数列分段【二分】
下一篇:YbtOJ 贪心算法课堂过关 例3 畜栏预定【贪心】

发表评论

最新留言

能坚持,总会有不一样的收获!
[***.219.124.196]2025年03月25日 13时45分13秒