[土]巨石滚滚
「土」巨石滚滚
https://ac.nowcoder.com/acm/problem/53681
这是道究极无敌贪心,需要贪的地方太多了,直接wa了五六次,其实我的代码也是很笨拙的,但是代码的思路还是挺清晰,可以一看的;代码建议自己写更优秀的。
//核心思路:当然是一贪到底;
给出的数据是无序的,所以我们要想出最优的排法尽量的让巨石把所有的障碍全部撞破,所以我们就要贪他;
所有的数据我们可以分为三种类型,分别是阻碍>恢复(撞到这种障碍之后自身稳定性必减),阻碍==恢复的(稳定性不变但是要考虑撞得破不),阻碍<恢复(撞这种之后自身稳定性增加),所以我们首先要撞的是第三种让自己的稳定性增加才能去撞击后面稳定性减少或者不变的阻碍,但是呢这还不够贪,在全部都是增加的阻碍中我们又按什么来撞呢??(当然是按阻碍性小的先撞,然后稳定性增加之后才能去撞后面阻碍性大的,
再之后其实稳定性不变的就可随便什么顺序,再这之后的稳定性减弱的数据中我们又该怎么撞呢?为了尽量多撞所以我们要将恢复力多的排在前面先撞,这样才能有足够多的稳定性去面对之后的阻碍。
思路就是这样,然后就看看我用代码实现吧(我的代码很蠢,可以看看思路就行了);
#include<iostream> #include<algorithm> #include<string.h> using namespace std; #define N 1000000 struct pp{ int a; int b; } s[N],t[N],z[N]; bool cmp1(pp a,pp b){//按阻碍从小到大排 return a.a<b.a; } bool cmp2(pp a,pp b){ return a.b>b.b;//恢复性从大到小排 } void check(int a,long long int b,int c,int d){ for(int i=0;i<a;i++){ b-=s[i].a; if(b<0){ cout<<"No"<<endl;//撞不破就输出 return ; } b+=s[i].b; } for(int i=0;i<d;i++){ b-=z[i].a; if(b<0){ cout<<"No"<<endl;//撞不破就输出 return ; } b+=z[i].b; } for(int i=0;i<c;i++){ b-=t[i].a; if(b<0){ cout<<"No"<<endl;//撞不破就输出 return ; } b+=t[i].b; } cout<<"Yes"<<endl;//之前都没输出结束,那么就可以撞完; return ; } int main(){ int n; cin>>n; while(n--){ int num,cnt=0,hua=0,gou=0; long long int x; cin>>num>>x; for(int i=0;i<num;i++){ int o,p; cin>>o>>p; if(o-p<0){//分类型储存在三个数组中 s[cnt].a=o; s[cnt].b=p; cnt++; }else{if(o-p>0){ t[hua].a=o; t[hua].b=p; hua++; }else{ z[gou].a=o; z[gou].b=p; gou++; } } } sort(s,s+cnt,cmp1); sort(t,t+hua,cmp2); //这有一点(我踩的坑)当我们看到多组数据是都喜欢初始化,其实这道题不用出示化, //因为排序是按照a到a+n排的,初始化会超时; check(cnt,x,hua,gou); } return 0; }