CFGym 100956D - Greedy Game【贪心】【优先队列】( 2015-2016 Petrozavodsk Winter Training Camp)

题目: 

 题目大意:

给n个物品,每个物品对A和B的价值不同,A先手并且A每次选剩余物品中对于他最大的物品,问不管A怎么选(可能有多个物品对于A的价值相同,但会影响B的所得),B都能得到的最大价值是多少?(换句话说就是最坏情况下B所能得到的最大价值)(这题题意读错两次,第三次才理解对,第一次以为是最好情况,第二次以为不管A怎么选,B都有办法拿到相同的价值,再从中取最大值)

题目分析:

一开始,我使用两个结构体数组存各自的价值和位置,各自sort,第一个数组在值相同的时候使用第二个数组的值进行排序,再根据对应位置标记vis数组,但是这样是错的,因为使用这种方法,如果一个物品x对于A价值很小,对于B价值很大,对于A,可能很后面选或者甚至于不选,但B却在开头就选了,这时存在另一个物品y对A和B价值很大,但对于B价值没有x大,在B选x的时候A选了y,然后B就无法选y,所以这样选不是最优的,因为x完全可以放后面选,也就是B的选择顺序不一定按照价值从大到小。

正确的贪心策略是A和B的数组用一个结构体存储,先对A的价值从大到小排序,如果物品对A的价值相等,那么按照物品对B的价值从大到小排序,那么A选择的每个物品都是当前对于A来说最大的,且对于B来说相对较大的,那么这时就对B构成了最坏情况,那么B如何通过决策在最坏情况下拿到最大价值呢?

我们可以先让B选择偶位置i上的物品,并将其放入小根堆,这时比较i + 1位置物品对B的价值和小根堆的堆顶元素大小,如果i+ 1位置上的物品对B的价值大小大于堆顶,则pop堆顶,push该位置的价值进小根堆,为什么这样做是对的?因为除去第一个物品,A和B就相当于B先手,那么B可以选择每队较大的物品,并且向后更新的时候,只会弃掉相对靠前的物品选择相对靠后的物品,不会产生其他影响。(有点难讲清楚,如果B弃掉靠后的物品选择相对靠前的物品,那么由于A后手会选择对他而言最大价值的物品,会把B待选择的物品给选掉)

代码:

#include <cstdio>
#include <iostream>
#include <algorithm>
#include <queue>
using namespace std;
const int N = 1e5 + 100;
typedef long long ll;
struct node{
    ll fi, se;
}a[N];
priority_queue<int, vector<int>, greater <int> > q;
bool cmp(node c, node d){
    if (c.fi == d.fi) return c.se > d.se;
    return c.fi > d.fi;
}
int main()
{
    int n;
    scanf("%d", &n);
    for (int i = 1; i <= n; ++i){
        scanf("%lld", &a[i].fi);
    }
    for (int i = 1; i <= n; ++i){
        scanf("%lld", &a[i].se);
    }
    sort(a + 1, a + 1 + n, cmp);
    ll sum = 0;
    for (int i = 2; i <= n; i += 2){
        q.push(a[i].se);
        int tmp = q.top();
        if (a[i + 1].se > tmp){
            q.pop();
            q.push(a[i + 1].se);
        }
    }
    while (!q.empty()){
        sum += q.top();
        q.pop();
    }
    printf("%lld\n", sum);
    return 0;
}

提供一组数组方便理解:

输入:

9
5 5 5 5 4 4 3 3 2
7 7 1 1 3 2 8 5 1

输出:23

 

评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值