zoukankan      html  css  js  c++  java
  • P1080 国王游戏

    链接

    P1080 国王游戏

    思路

    首先我们先思考一下当只有两个大臣的时候怎么做(当题目没有思路的时候,先考虑数据范围小的情况往往是有帮助的)。 如果国王左手上的数是 (a_0),两个大臣左右手上的数是(a_1,b_1,a_2,b_2);那么有两种排法: 第一个大臣排在前面,那么第一个大臣获得 (a_0 / b_1) 奖赏,第二个获得 (a_0a_1 / b_2) 奖赏,奖赏最多的大臣获得的奖赏就是 (max(a_0 / b_1, a_0a_1 / b_2))。 同样,如果第二个大臣排在前面,答案就是(max(a_0 / b_1, a_0a_1 / b_2))

    比较 (ans_1=max(a_0 / b_1, a_0a_1 / b_2))(ans_2=max(a_0 / b_1, a_0a_1 / b_2)),可以写成 (ans_1=a_0 max(b_2,a_1cdot b_1) / b_1cdot b_2 ans_2=a_0 max(b_1,a_2cdot b_2) / b_1cdot b_2) 可以想象,如果 (a_1cdot b_1 ≤ a_2cdot b_2,)那么 $ans_1 $肯定更小,因为这种情况下 $a_1cdot b_1 ≤ a_2cdot b_2 $而 (b_2 ≤ a_2cdot b_2),所以 (max(b_2,a_1cdot b_1) ≤ a_2cdot b_2 ≤ max(b_1,a_2cdot b_2)) 同理,如果$ a_1cdot b_1 > a_2cdot b_2(那么) ans_2 (更小。 于是我们得到一个结论:只有两个人时,把) a_i cdot b_i $更小那个放到前面一定更优。

    当有更多大臣的时候呢? 考虑最优解满足什么性质。如果我们交换最优解中两个相邻的大臣,那么他们前面的大臣得到的奖赏显然不受影响;而他们后面的大臣也不受影响。(想一想,为什么) 那么把这两个大臣单独拎出来,根据之前的结论,最优解中一定是 ab 较小的放到前面。 这样的话,我们得出结论:最优解中相邻两个大臣,前面的 ab 一定更小。否则可以交换相邻的大臣使得答案更小。

    于是最优解肯定是按大臣的 $acdot b (排序后的结果。所以将大臣按) acdot b $排好序,计算每个大臣的奖赏就可以了(这题代码难点在于高精度) 通过这道题我们看出一种贪心的分析方式,它尤其适用于“将若干个物品重新排列使得___最小/最大”的问题: 假设我们有一组解,考虑如何调整能使它更优(对于重新排列,一般是交换相邻物品); 最优解一定不能调整。

    以来来自《noip杂题选讲 by rqy》

    代码

    主要是高精度(

    #include<iostream>
    #include<cstdio>
    #include<algorithm>
    #include<cmath>
    #include<queue>
    #include<stack>
    #include<vector>
    #include<map>
    #include<string>
    #include<cstring>
    using namespace std;
    struct num {
    	int len,s[10005];//len为数字位数,s数组为每一位上的数字
    	num(int a=0) { //构造函数
    		len=0;
    		memset(s,0,sizeof(s));
    		while(a) {
    			len++;
    			s[len]=a%10;
    			a/=10;
    		}
    	}
    	num operator * (const num &a) const {
    		num c;
    		int x;
    		for(int i=1; i<=a.len; ++i) {
    			x=0;
    			for(int j=1; j<=len; ++j) {
    				c.s[i+j-1]+=a.s[i]*s[j]+x;
    				x=c.s[i+j-1]/10;
    				c.s[i+j-1]%=10;
    			}
    			c.s[i+len]=x;
    		}
    		c.len=a.len+len;
    		while(!c.s[c.len] && c.len!=1) c.len--;
    		return c;
    	}
    	num operator / (const int &a) const { //重载整除运算(高精)
    		num c;
    		int x=0;
    		c.len=len;
    		for(int i=c.len; i>=1; --i) {
    			x=x*10+s[i];
    			c.s[i]=x/a;
    			x%=a;
    		}
    		while(!c.s[c.len] && c.len!=1) c.len--;
    		return c;
    	}
    	bool operator < (const num & x) const {//重载'<'(高精比较大小),max函数中要用
    		if(len!=x.len) return len<x.len;
    		for(int i=len; i>0; i--)
    			if(s[i]!=x.s[i])
    				return s[i]<x.s[i];
    		return 0;
    	}
    };
    struct node { //表示大臣的结构体
    	int a,b,c;
    } p[10005];
    int cmp(node a,node b)
    {
    	return a.c<b.c;
    }
    int n;
    int main() {
    	cin>>n;
    	for(int i=0; i<=n; ++i) {
    		cin>>p[i].a>>p[i].b;
    		p[i].c=p[i].a*p[i].b;
    	}
    	num sum(p[0].a),ans;
    	sort(p+1,p+n+1,cmp);
    	for(int i=1; i<=n; ++i) {
    		ans=max(ans,sum/p[i].b);
    		sum=sum*p[i].a;
    	}
    	for(int i=ans.len; i>=1; i--)
    		cout<<ans.s[i];
    	return 0;
    }
    
  • 相关阅读:
    78. Subsets
    93. Restore IP Addresses
    71. Simplify Path
    82. Remove Duplicates from Sorted List II
    95. Unique Binary Search Trees II
    96. Unique Binary Search Trees
    312. Burst Balloons
    程序员社交平台
    APP Store开发指南
    iOS框架搭建(MVC,自定义TabBar)--微博搭建为例
  • 原文地址:https://www.cnblogs.com/pyyyyyy/p/11297511.html
Copyright © 2011-2022 走看看