贪心专题训练
本周开始在洛谷上刷题了,但是因为最近洛谷不能注册账号了,所以一直和室友用同一个账号,刷的题不多,但是也遇到了一些比较有意思的题。这周主要刷贪心类型的题,顺便复习了sort函数。
1 魔法
Ac代码
#include <iostream>
#include<algorithm>
using namespace std;
const long long int maxn=100000+1;
struct node{
int pre;
int date;
};
bool cmp(node a,node b){
return a.pre+a.date>b.pre+b.date;}
int main()
{
int t;
cin>>t;
while(t--){
int n,m;
cin>>n>>m;
node a[maxn];
for(int i=0;i<n;i++)
cin>>a[i].pre>>a[i].date;
sort(a,a+n,cmp);
int flag=-1;
for(int i=0;i<n;i++)
if(a[i].pre<m){m+=a[i].date;if(m<=0){flag=1;break;}}
else {flag=1;break;}
if(flag==1){
cout<<"-1s"<<endl;
}else {
cout<<"+1s"<<endl;}
}
}
题目:
cjwssb知道是误会之后,跟你道了歉。你为了逗笑他,准备和他一起开始魔法。不过你的时间不多了,但是更惨的是你还需要完成n个魔法任务。假设你当前的时间为T,每个任务需要有一定的限制ti表示只有当你的T严格大于ti时你才能完成这个任务,完成任务并不需要消耗时间。当你完成第i个任务时,你的时间T会加上bi,此时要保证T在任何时刻都大于0,那么请问你是否能完成这n个魔法任务,如果可以,输出+1s,如果不行,输出-1s。
这道题的精髓在于
bool cmp(node a,node b){
return a.pre+a.date>b.pre+b.date;}
这个排序十分关键。看到题时,很显然能够想到要先算bi大于0的,这样能保证时间足够。一种思路是用两个结构体,一个存bi大于0的,一个存bi小于0的,分类讨论,不过这个方法比较麻烦,没有这个方法简洁。
具体推理过程是:
时间T可能大于大于t1,可是加上b1导致T小于t2,而T加上b2但是大于t1,所以满足方程的公式为
1 T+b1<t2
2 T+b2>t1
3 t1-b2<t2-b1
既 t1+b1<t2+b2
所以应该算t2加b2大的优先,带入特解发现成立。
2 PLES COCI2011-2012#1
#include <iostream>
#include<algorithm>
using namespace std;
const long long int maxn=100000+5;
int a[maxn];
int a1[maxn];
int a2[maxn];
int a3[maxn];
int main()
{
int n;
int s=0;
int s1=0;
int s2=0;
int s3=0;
cin>>n;
for(int i=0;i<n;i++){//a对a3 a1对a2
int k;
cin>>k;
if(k>0){a[s]=k;s++;}
else {a2[s2]=-k;s2++;}
}
for(int i=0;i<n;i++){
int k;
cin>>k;
if(k>0){a1[s1]=k;s1++;}//女
else {a3[s3]=-k;s3++;}
}
int count=0;
sort(a,a+s);
sort(a1,a1+s1);
sort(a2,a2+s2);
sort(a3,a3+s3);
for(int i=0,j=0;i<s&&j<s3;j++)
if(a[i]<a3[j]){i++;count++;}
for(int i=0,j=0;i<s1&&j<s2;j++)
if(a1[i]<a2[j]){i++;count++;}
cout<<count<<endl;
}
题意:
求如果遵照每个人的意愿,最大的舞伴对数是多少。
这道题是很明显的贪心题,但是在做这道题时我总是有很多数据过不了。具体思路是,用4个数组分别存男生大于0和小于0的数以及女生大于0和小于0的数。
但是需要注意一点i和j的顺序。
例如第一个for循环,表示男生必须找比自己高的,两个数组从小到大排序,无论是否成立,那么女生都得选一个更高的,理由是,如果if不成立,那么男生就不能选一个更高的。
总结: 这周主要是刷贪心专题 普及/提高,下周目标也是主要刷贪心专题,以及搜索专题。