按照每个大臣左、右手数的乘积从小到大排序是最优的
证明:
n名大臣左、右手的数分别为
a[1]~a[n] b[1]~b[n]
国王的左、右手数字为a[0]和b[0]
第i个大臣获得的金币数为
(a[0]a[1]a[2]···a[i - 1]) / b[i] (式子1)
第i+1个大臣获得的金币数为
(a[0]a[1]a[2]···a[i]) / b[i + 1] (式子2)
当把第i个大臣和第i+1个大臣交换后
交换前第i+1个大臣现在获得的金币数为
(a[0]a[1]a[2]···a[i - 1]) / b[i + 1] (式子4)
交换前第i个大臣(现在是第i+1个)现在获得的金币数为
(a[0]a[1]a[2]···a[i - 1] * a[i+1]) / b[i] (式子3)
很显然交换i和i+1大臣其他大臣的金币数量是不变的
现在只要比较交换后的2个大臣拥有最多金币的数量是变多还是变少
如果交换后2个大臣中拥有最多金币的数量变多,则不应该交换
如果交换后2个大臣中拥有最多金币的数量变少,则应该交换
即要比较max(max(式子1 , 式子2) , max(式子3 , 式子4))
如果最大值是第一个max,则应该交换
否则不应该交换
整理得:
max(max(1/b[i] , a[i]/b[i+1]) , max(1/b[i+1] , a[i+1]/b[i]))
4个式子都乘与b[i]b[i+1]得:
max(max(b[i+1] , a[i]b[i]) , max(b[i] , a[i+1]b[i+1]))
因为每个数字都是正数
所以 a[i]b[i] >= b[i] a[i+1]b[i+1] >= b[i+1]
如果a[i]b[i] <= a[i+1]b[i+1]
那么a[i+1]b[i+1] >= b[i] 则max(b[i] , a[i+1]b[i+1])的结果应该是a[i+1]b[i+1]
max(b[i+1] , a[i]b[i])对于这个式子不管谁最大都小于a[i+1]b[i+1]
则可以说明交换后拥有最多金币的大臣的金币数量变大
所以不应该交换
如果a[i]b[i] >= a[i+1]b[i+1]
同理得交换前拥有最多金币的大臣的金币数量变大
所以不应该交换
结论:
如果a[i]b[i] <= a[i+1]b[i+1] 不交换
如果a[i]b[i] >= a[i+1]b[i+1 交换
设a[i]b[i] = c[i] a[i+1]b[i+1] = c[i+1]
那么就有
如果c[i] <= c[i+1] 不交换
如果c[i] >= c[i+1] 交换
可以发现要交换的2个值他们是互为逆序对
交换一次后逆序对数量减少1
那么最后逆序对的数量一定是0
则按照c[i]的值从小到大排序是最优的
即按照a[i]*b[i]的值从小到大排序(不考虑国王)
#include <iostream>
#include <algorithm>
#include <vector>
using namespace std;
const int N = 1010;
struct Poeple{
int left;
int right;
int val; //存的是左手乘右手的值
}people[N];
int n;
bool compare(struct Poeple a , struct Poeple b){
return a.val < b.val;
}
vector<int> div(vector<int> a, int b){ //高精度除法 a/b
vector<int> ans; //结果
int t = 0; //余数
//从高位开始除b
for (int i = a.size() - 1;i >= 0;i--){
t = t * 10 + a[i];
ans.push_back(t / b);
t %= b;
}//for
//现在ans数组的格式是高位在前 需要翻转
reverse(ans.begin() , ans.end());
//去掉前导0
while(ans.size() > 1 && ans.back() == 0){
ans.pop_back();
}
return ans; //返回结果
}
//高精度乘法 高精度*低精度
vector<int> mul(vector<int> a , int b){
vector<int> ans;
int t = 0; //进位
for (int i = 0;i < a.size();i++){
t += a[i] * b;
ans.push_back(t % 10);
t /= 10;
}//for
while(t){
ans.push_back(t % 10);
t /= 10;
}//if
return ans;
}
vector<int> Max(vector<int> a , vector<int> b){
if(a.size() > b.size()) return a;
else if (a.size() < b.size()) return b;
//从高位开始比较
for (int i = a.size() - 1;i >= 0;i--){
if(a[i] > b[i]) return a;
if(a[i] < b[i]) return b;
}
//a和b相等
return a;
}
int main (){
cin >> n;
cin >> people[0].left >> people[0].right; //国王
people[0].val = people[0].left * people[0].right;
for (int i = 1;i <= n;i++){
int a = 0;
int b = 0;
cin >> a >> b;
int c = a * b;
people[i] = {a , b, c};
}
sort(people + 1 , people + 1 + n , compare); //按照val排序
vector<int> cnt(1 , 1);
vector<int> res(1 , 0);
//res = div(cnt , 2);
//for (auto i : cnt) cout << i << endl;
for (int i = 0;i <= n;i++){
if(i) res = Max(res , div(cnt , people[i].right));
cnt = mul(cnt , people[i].left);
}
for (int i = res.size() - 1;i >= 0;i--){
cout << res[i];
}
return 0;
}