NOIP2012 国王游戏(贪心)

原题链接

题目描述

在这里插入图片描述

输入描述

在这里插入图片描述

输出描述

在这里插入图片描述

输入样例

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;
} 

猜你喜欢

转载自blog.csdn.net/laysan/article/details/119652369