【贪心】Ybt_国王游戏

题目

每个大臣在左、右手上有个整数,国王自己左、右手也有个整数。然后,让这 n 位大臣排成一排,国王站在队伍的最前面。每位大臣获得的金币数分别是:排在该大臣前面的所有人的左手上的数的乘积除以他自己右手上的数,然后向下取整得到的结果。

国王不希望某一个大臣获得特别多的奖赏,所以他想请你帮他重新安排一下队伍的顺序,使得获得奖赏最多的大臣,所获奖赏尽可能的少,注意,国王的位置始终在队伍的最前面。

输入

第一行一个数,n
第二行两个数,是国王左右手的数字
接下来 n 行,是各大臣左右手的数字

输出

一个数,表示获得奖赏最多的大臣所获得的奖赏数。


对于相邻的两个大臣,设第 i 人前面的人左手上的乘积为 Si ,左手的数字为 L, 右手的数字为R,易得:

交换前 交换后
第i位大臣 S i − 1 / R i S_{i-1}/R_i Si1/Ri S i − 1 / R i + 1 S_{i-1}/R_{i+1} Si1/Ri+1
第i+1位大臣 S i − 1 ∗ L i / R i + 1 S_{i-1}*L_i/R_{i+1} Si1Li/Ri+1 S i − 1 ∗ L i + 1 / R i S_{i-1}*L_{i+1}/R_i Si1Li+1/Ri

而相邻两位交换并不影响前后大臣所获奖赏。于是比较相邻两位交换会不会更优。
考虑这两式子的大小关系:
m a x ( S i − 1 R i , S i − 1 ∗ L i R i + 1 ) max\left ( \frac{S_{i-1}}{R_i}, \frac{S_{i-1}*L_i}{R_{i+1}}\right ) max(RiSi1,Ri+1Si1Li) m a x ( S i − 1 R i + 1 , S i − 1 ∗ L i + 1 R i ) max\left ( \frac{S_{i-1}}{R_{i+1}}, \frac{S_{i-1}*L_{i+1}}{R_{i}}\right ) max(Ri+1Si1,RiSi1Li+1)
经过化简,得:
m a x ( R i + 1 , L i ∗ R i ) max\left ( R_{i+1}, L_i*R_i\right ) max(Ri+1,LiRi) m a x ( R i , L i + 1 ∗ R i + 1 ) max\left ( R_{i}, L_{i+1}*R_{i+1}\right ) max(Ri,Li+1Ri+1)

由于 L,R,都是正整数,所以和正整数相乘必定大于等于本身。
所以可以转换成 L i ∗ R i L_i*R_i LiRi L i + 1 ∗ R i + 1 L_{i+1}*R_{i+1} Li+1Ri+1 的比较。

遂以 L ∗ R L*R LR 的值从小到大排序,然后统计答案。

  • 注意要用高精度

代码

#include<cstdio>
#include<iostream>
#include<algorithm>
using namespace std;
int n, a, b, flag;
struct mstm{
    
    
	int l,r,c;
} A[5000];
struct asdf{
    
    
	int s[5000];
} K, L, Ans;
bool cmp(mstm x, mstm y){
    
    
	return x.c < y.c;
}
asdf operator *(asdf x, int y){
    
      //高精乘低精
	int jw = 0;
	for(int i = 1; i <= 4000; ++i){
    
    
		x.s[i] = x.s[i] * y + jw;
		jw = x.s[i] / 10;
		x.s[i] %= 10;
	}
	return x;
}
asdf operator /(asdf x, int y){
    
     //高精除低精
	int l = 0;
	for(int i = 4000; i >= 1; --i){
    
    
		l = l * 10 + x.s[i];
		x.s[i] = l / y;
		l = l - x.s[i] * y;
	}
	return x;
}
asdf maxx(asdf x, asdf y){
    
      //取最大值
	for(int i = 4000; i > 0; --i){
    
    
		if(x.s[i] > y.s[i]) return x;
		if(x.s[i] < y.s[i]) return y;
	}
	return x;
}
int main(){
    
    
	scanf("%d%d%d", &n, &a, &b);
	for(int i = 1; i <= n; ++i){
    
    
		scanf("%d%d", &A[i].l, &A[i].r);
		A[i].c = A[i].l * A[i].r;
	}
	sort(A+1, A+1+n, cmp);  //排序
	K.s[1] = a;
	K = K * 1;
	for(int i = 1; i <= n; ++i){
    
      //求每位大臣获得的奖赏
		L = K / A[i].r;
		K = K * A[i].l;
		Ans = maxx(Ans, L);
	}
	for(int i = 4000; i >= 1; --i){
    
      //输出答案
		if(Ans.s[i]!=0) flag = 1;
		if(flag == 1) printf("%d",Ans.s[i]);
	}
}

猜你喜欢

转载自blog.csdn.net/qq_42937087/article/details/112131620