题目描述
输入描述
输出描述
输入样例
3
1 1
2 3
7 4
4 6
输出样例
2
样例说明
数据范围
本题中不难发现,交换任意两个大臣时,只会影响他们各自的金币数,而不会影响他们之前和之后的大臣的金币数,因此可以考虑贪心对比两个大臣交换前后的金币。假设相邻的两个大臣中,其左右手分别为 a1,b1,a2,b2,之前所有人的左手乘积总和为 sum,可得交换前为 sum * a1 / b2,交换后为 sum * a2 / b1,若存在交换前 > 交换后,可推出 a1 * b1 > a2 * b2,此时交换两大臣可使获得金币减少。即对大臣左右手金币的乘积进行上升排列即是最优方法。
本题坑点是,需要使用高精度!!
参考代码
#include <bits/stdc++.h>
using namespace std;
struct a{
int l,r;
}a[1010];
int k[1010];
int f[1010],fs[1010];
int main(){
int n;
cin>>n;
int m;
for(int i=0;i<=n;i++){
cin>>a[i].l>>a[i].r;
k[i]=a[i].l*a[i].r;
}
for(int i=1;i<n;i++)
for(int j=1;j<=n-i;j++)
if(k[j]>k[j+1]){
swap(a[j].l,a[j+1].l);
swap(a[j].r,a[j+1].r);
swap(k[j],k[j+1]);
}
f[0]=a[0].l;
long double s=0,t=a[0].l;
int si=0;
for(int i=1;i<=n;i++){
if(t/a[i].r>s){
s=t/a[i].r;
m=0;
for(int j=n-1;j>=0;j--){
m=10000*m+f[j];
fs[j]=m/a[i].r;
m%=a[i].r;
}
si=i;
}
t*=a[i].l;
m=0;
for(int j=0;j<=n-1;j++){
m+=f[j]*a[i].l;
f[j]=m%10000;
m/=10000;
}
}
m=0;
for (int j=n-1; j>=0; j--) {
if (m==1){
if(fs[j]<10) cout<<"000";
else if (fs[j]<100) cout<<"00";
else if (fs[j]<1000) cout<<"0";
cout<<fs[j];
}
else if(fs[j]>0){
cout<<fs[j];
m=1;
}
}
return 0;
}