soj 4558 Coupon

题目链接:Coupon


题意大致就是给你n对数,每对数代表一场电影,k张优惠券,m的钱,然后这n场电影分别有两个值,一个是不使用优惠券的价格,一个是使用优惠券的价格,然后问你在k张优惠券m钱的限制下能够看多少场电影,这道题贪心的做法是错误的,因为可以被无情的hack掉,但是可以AC这道题,所以数据没有考虑到一些情况吧,怀疑标程写错,还是给出贪心做法,正解以后会找时间补掉,贪心想法是不管打折前后,反正我把每个数打折前和打折后的价格统统扔进一个数组里面,然后定义一个flag代表这个数是打折的还是不打折的,再定义一个se代表这个数所在的位置是不是被访问过(因为每个位置打折前后的值你肯定不可能全选,只能选其中一个),然后把那个数组从小到大排,遍历一遍,如果sum加当前值大于m就break,否则继续判断,如果flag为0代表是不打折的前项,直接加进sum,cot加加,如果flag为1还要判断k是不是大于等于1,因为最多使用k个优惠券,然后再判断这些之前还要判断这个位置是不是被用过,没用过我再进行上面操作,大概这样贪就可以AC了,但是这组数据贪心的答案是1,而正确答案应该是2,所以,贪心解法错误,正解大概是两个优先队列瞎搞,还是扔一发贪心的解法吧

#include <bits/stdc++.h>

using namespace std;
typedef long long ll;

struct node{
    int value,se,flag;
}tick[100005];

ll n,k,m,x,y;
bool vis[100005];

bool cmp(node a,node b){
    if(a.value == b.value) return a.flag < b.flag;
    return a.value < b.value;
}

int main(){
    ios::sync_with_stdio(false);
    while(cin>>n>>k>>m){
        for(int i = 0;i < n;i++){
            cin>>x>>y;
            tick[i].value = x;
            tick[i].flag = 0;
            tick[i].se = i;
            tick[n+i].value = y;
            tick[n+i].flag = 1;
            tick[n+i].se = i;
        }
        memset(vis,false,sizeof(vis));
        sort(tick,tick+n*2,cmp);
        ll sum = 0,cot = 0;
        for(int i = 0;i < n*2;i++){
            if(sum + tick[i].value <= m){
                if(!vis[tick[i].se]){
                    if(tick[i].flag == 0) sum += tick[i].value,vis[tick[i].se] = true,cot++;
                    else{
                        if(k >= 1) k--,sum += tick[i].value,vis[tick[i].se] = true,cot++;
                        else continue;
                    }
                }
                else continue;
            }
            else break;
        }
        cout<<cot<<endl;
    }
    return 0;
}

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值