链接:https://ac.nowcoder.com/acm/contest/911/D
来源:牛客网
 

时间限制:C/C++ 1秒,其他语言2秒
空间限制:C/C++ 32768K,其他语言65536K
Special Judge, 64bit IO Format: %lld

题目描述

有 n件商品,第 i件商品价格为 a[i],购买后,其它所有未购买的商品价格乘上 p[i],现在要买下所有商品,输出最小耗费。

输入描述:

第一行一个整数 n(n≤105)n(n≤105),接下来 n 行,第 i 行两个数字a[i],p[i],其中 a[i] 为整数,p[i] 为浮点数,1≤a[i]≤105,0≤p[i]≤11≤a[i]≤105,0≤p[i]≤1。

输出描述:

保留六位小数输出。

示例1

输入

复制

2
1 0.5
10 1

输出

复制

6.000000

示例2

输入

复制

3
27545 0.79
77924 0.1
64441 0.66

输出

复制

85769.339000

备注:

* 样例 1:先买 1 号商品,再买 2 号商品。
* 样例 2:先买 2 号商品,再买 1 号,最后买 3 号。

很有意思的题目

初见本题想到的就是贪心

开始的贪心策略是看a*p从小到大 交上去当然是不对的

然后看了题解才知道原来是这种贪心

那么这种贪心是什么原理呢

显然我们可以看出 当只有两个元素是上面的表达式就是将两个元素不同顺序的取的价值

那么只要我们保证没两个元素都符合以上的规律那么就一定是符合规律得了

代码

#include<bits/stdc++.h>
using namespace std;
struct node
{
    double x;
    double y;
    double z;
    friend bool operator < (const node p,const node q)
    {
        return p.x+p.y*q.x<q.x+q.y*p.x;
    }
}a[100005];
int main()
{
    int n;
    cin>>n;
    double ans=0;
    double num=1;
    double sum=0;
    for(int i=1;i<=n;i++)
    {
        cin>>a[i].x>>a[i].y;
        sum+=a[i].x;
    }
    sort(a+1,a+1+n);
    for(int i=1;i<=n;i++)
    {
        //cout<<a[i].x<<" "<<a[i].y<<endl;
        ans=ans+a[i].x*num;
        num=num*a[i].y;
    }
    printf("%.6lf\n",ans);
}