题目描述

你要买n件物品,其中有一些是凳子。
商场正在举行促销活动,如果购物车中有至少一个凳子,那么你可以半价购买这个购物车中最贵的一个物品。
你有m辆购物车,请最小化你的花费。

输入描述:

第一行一个整数t表示数据组数 (1 ≤ t ≤ 100)。
每组数据第一行两个整数n,m (1 ≤ n,m ≤ 1000),接下来n行每行两个整数ai,bi,分别表示第i件物品的价格以及它是否是凳子 (1 ≤ ai ≤ 105, 0 ≤ bi ≤ 1)。

输出描述:

每组数据输出一行一个实数表示最小花费,保留一位小数。

输入

2
5 1
1 0
2 1
3 1
4 0
5 0
5 10
1 0
2 1
3 1
4 0
5 0

输出

12.5
10.5

分析:

将每一个凳子看成一次打折的机会,然后对所有商品按照价格从大到小排序,让打折机会尽可能用在价格排在前面的商品上(贪心思想)。但是打折机会可能会受到购物车数量的限制,所以我们将打折机会和购物车数量取一个最小值,作为最终的打折次数

#include<bits/stdc++.h>
using namespace std;
#define js ios::sync_with_stdio(0);cin.tie(0);cout.tie(0);
typedef long long ll;
int t;
int n,m;
const int N=1005;
int a[N],b[N];
bool cmp(int a,int b){
    return a>b;
}
int main(){
    scanf("%d",&t);
    while(t--){
        int cnt=0;//cnt代表打折次数,也就是凳子的个数
        memset(a,0,sizeof(a));//初始化
        memset(b,0,sizeof(b));
        scanf("%d%d",&n,&m);
        for(int i=0;i<n;i++){
            scanf("%d%d",&a[i],&b[i]);
            if(b[i]==1){
                cnt++;
            }
        }
        sort(a,a+n,cmp);
        cnt=min(cnt,m);//最终打折次数=min(凳子个数,购物车个数)
        double ans=0;
        //统计被打折商品的价格
        for(int i=0;i<cnt;i++){
            ans+=a[i]*1.0/2;
        }
        //统计其他商品的价格
        for(int i=cnt;i<n;i++){
            ans+=a[i];
        }
        printf("%.1lf\n",ans);//最后这里注意保留1位小数
    }
    return 0;
}