NC16561-国王的游戏
题目链接:https://ac.nowcoder.com/acm/problem/16561
参考题解链接:https://ac.nowcoder.com/acm/contest/view-submission?submissionId=46518796
题意:1个国王给n个大臣分奖赏,国王和大臣左右手中分别有值,相当于给定(1+n)个l和r值,第一个为国王,每个大臣所得的奖赏为 这个大臣前的所有人左手值的乘积÷本大臣右手值,要求排序使得奖赏最多的大臣所得金币最少,输出奖赏最多大臣的奖赏数值。
思路:贪心,本题相当于对所有大臣进行排序,使得上述最大奖赏值最小,进行局部最优解分析:
如果存在两个大臣 大臣a左右手值为al和ar,大臣b 左右手值为bl,br,两大臣前左手乘积为L:
当大臣a在b前边的时候
①大臣a所得奖赏:\(\frac{L}{ar}\)
②大臣b所得奖赏:\(\frac{L\times al}{br}\)
当大臣b在a前边的时候:
③大臣a所得奖赏:\(\frac{L\times bl}{ar}\)
④大臣b所得奖赏:\(\frac{L}{br}\)
由于al,ar,
明显:\(①\leq ③\),\(②\geq ④\) ,假设ab顺序为正解,则只需要满足\(③\leq②\)即可实现ab顺序中的奖赏最多的大臣所获得的奖赏值小于等于ba顺序中奖赏最多的大臣所获奖赏值。
将除法公式传换成乘法来避免精度和除0等可能存在问题,得到排序的依据为:\(al\times ar \geq bl\times br\) 通过这个顺序进行排序即可达到局部贪心实现最优解
坑点:本题数据范围导致40%的测试数据中 左手中的值乘积会爆long long 所以需要加一个大数乘int,大数除int 以及大数之间大小比较的处理,具体实现有参考上述题解链接所指题解。
反思:要认真分析数据范围,可能会出现爆int或者long long情况哎
#include<cstdio>
#include<algorithm>
using namespace std;
struct node{
int l,r;
}a[(int)1e4+5];
bool cmp(struct node s,struct node t){
return 1LL*s.l*s.r<1LL*t.l*t.r;
}
struct num{
int number[10005]={0};//在0位置存储数值长度
}ans,res;
void mul(int x){
int len=ans.number[0];
for(int i=1;i<=len;i++){
ans.number[i]*=x;
}
for(int i=1;i<=len;i++){
ans.number[i+1]+=ans.number[i]/10;
ans.number[i]%=10;
}
while(ans.number[len+1]>0){
len++;
ans.number[len+1]=ans.number[len]/10;
ans.number[len]%=10;
}
ans.number[0]=len;
}
struct num div(struct num & temans,int x){
int num=0;
struct num temres;
int len=temans.number[0];
for(int i=len;i>=1;i--){
num=num*10+temans.number[i];
temres.number[i]=num/x;
num%=x;
}
while(temres.number[len]==0)len--;
temres.number[0]=len;
return temres;
}
bool comparen(const struct num l,const struct num r){//>
if(l.number[0]>r.number[0])return true;
for(int i=l.number[0];i>=1;i--){
if(l.number[i]>r.number[i])return true;
else if (l.number[i]<r.number[i])return false;
}
return false;
}
int main (){
int n;
scanf("%d",&n);
for(int i=0;i<=n;i++){
scanf("%d%d",&a[i].l,&a[i].r);
}
sort(a+1,a+n+1,cmp);
int s=a[0].l,len=1;
while(s){
ans.number[len++]=s%10;
s/=10;
}
ans.number[0]=len-1;
for(int i=1;i<=n;i++){
struct num tem=div(ans,a[i].r);
if(comparen(tem,res))res=tem;
mul(a[i].l);
}
for(int i=res.number[0];i>=1;i--)
printf("%d",res.number[i]);
return 0;
}
没进行高精度处理,只能过60%的代码
#include<cstdio>
#include<algorithm>
using namespace std;
struct node{
int l,r;
}a[(int)1e4+5];
bool cmp(struct node s,struct node t){
return 1LL*s.l*s.r<1LL*t.l*t.r;
}
int main (){
int n;
scanf("%d",&n);
for(int i=0;i<=n;i++){
scanf("%d%d",&a[i].l,&a[i].r);
}
sort(a+1,a+n+1,cmp);
long long ans=a[0].l;
long long res=0;
for(int i=1;i<=n;i++){
res=max(res,ans/a[i].r);
ans=1LL*ans*a[i].l;
}
printf("%lld",res);
return 0;
}

浙公网安备 33010602011771号