题目链接:​​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;
}