国王游戏【贪心+证明】

感想:

已经做了这么多到贪心题目,感觉大致的做法有以下几种。

1.看到题目和以前做过的题目差不多或者类似,那么就把想法过度到以前做过的题上。

2.直接分析,找出几种方法,进行类比。

3。猜猜猜,假设猜测是正确,然后反证,得到的结果合理,那么贪心成立。


-----------------------------------------------分界线---------------------------------------------------------

以下这题,就是靠猜出来的。




image

假设以ai*bi从大到小排序是最优策略,那么我们假设其中有一对逆序对,也就是ai*bi > ai+1 * bi+1.

接下来分析它交换之前,和交换之后的最大值的变化。

交换之前和交换之后结果。

image

提取公因式就变成比较后乘上结果b[i]*b[i+1]就变成如下结果


image

又因为Ai*Bi >= Bi, 且Ai*Bi > Ai+1 * Bi+1 而且Ai+1 * Bi+1 >= Bi+1

所以就有 max(Bi, Ai+1 * Bi+1) < = Ai*Bi <= max(Bi+1,Ai*Bi);所以可得交换后的最大值不大于交换前的结果,可以得到当ai*bi > ai+1 * bi+1时交换时最好的策略,也就时保证局部最优解。

  1 #include <iostream>
  2 #include <algorithm>
  3 #include <vector>
  4 #include <cstring>
  5 using namespace std;
  6 
  7 typedef pair<int, int> PII;
  8 const int N = 1010;
  9 
 10 int n;
 11 PII p[N];
 12 vector<int> mul(vector<int>a, int b)//乘法
 13 {
 14     vector<int> c;
 15     int t = 0;
 16     for (int i = 0; i < a.size(); i ++ )
 17     {
 18         t += a[i] * b;
 19         c.push_back(t % 10);
 20         t /= 10;
 21     }
 22     while (t)
 23     {
 24         c.push_back(t % 10);
 25         t /= 10;
 26     }
 27     return c;
 28 }
 29 vector<int> div(vector<int> a, int b){
 30     vector<int> c;
 31     int t = 0;
 32     bool is_first = true;
 33     for(int i = a.size() - 1; i >= 0; -- i){
 34         t = t*10 + a[i];
 35         int x = t / b;
 36         if (!is_first || x){//防止前面出现零
 37             is_first = false;
 38             c.push_back(x);
 39         }
 40         t %= b;
 41     }
 42     reverse(c.begin(), c.end());
 43     return c;
 44 }
 45 vector<int> max_vec(vector<int> a, vector<int> b){
 46     if(a.size() > b.size()) return a;
 47     if(a.size() < b.size()) return b;
 48     if(vector<int>(a.rbegin(),a.rend()) > vector<int>(b.rbegin(), b.rend())) return a;
 49     return b;
 50 
 51 }
 52 int main(){
 53     cin >> n;
 54     for(int i = 0, a, b; i <= n; ++ i){
 55         cin >> a >> b;
 56         p[i] = make_pair(a*b, a);
 57     }
 58     sort(p + 1, p + n + 1);//按a*b从小到大排序
 59     vector<int> product(1, 1);//初始化容器加入一个元素为1
 60 
 61     vector<int> res(1, 0);//用来存入最大值
 62     for (int i = 0; i <= n; ++ i){
 63         if (i) res = max_vec(res, div(product, p[i].first/p[i].second));//自定义比较函数
 64         product = mul(product, p[i].second);//乘积
 65     }
 66     for (int i = res.size() - 1; i >= 0; -- i) cout << res[i];//输出答案
 67     cout << endl;
 68     return 0;
 69 }
posted @ 2020-04-15 12:19  ACWink  阅读(74)  评论(0编辑  收藏  举报