(贪心)洛谷P2887 [USACO07NOV]防晒霜Sunscreen

一、算法分析

贪心策略是将牛按照minspf的降序排,然后在尽可能满足当前牛的情况下,优先取spf值大的防晒霜。
这样选择的原因是本题的特点(也是一些其它贪心类问题的特点),即如果我放弃了当前的牛,后面的情况也只能一样或更差。题目要求找出可满足的最多牛,如果我们放弃了当前牛,可能导致后面有一个牛用了本来打算给当前牛的防晒霜,也可能没有,但是无论如何,答案不会因为我们的刻意放弃而增加。所以基本的贪心策略是尽量满足当前牛。
进一步分析,从处理过程来看,我们是从左向右扫描数组,也就是说牛是只扫一遍,过了就过了,那么重要的就是防止我们产生“后悔”。因此要将牛按照minspf的降序排,这样即使错过了当前牛,后面的牛也可以在minspf这里满足条件。
然后分析maxspf,对于牛来说,我们只能对它的minspf或maxspf的其中一个排序。所以根据前面的分析,对牛排序之后,maxspf是乱序的,那么应该如何保证后面不会后悔,这时就只能对防嗮霜进行排序了。将防晒霜按照降序排序,每次优先选择spf大的。因为这样选择,尽量使得每个前面的奶牛都尽量选“区间”(防晒霜的spf减牛的minspf)范围大的,这样“浪费”少(个人这样理解的,感觉存疑)。

二、代码及注释

#include
#include
#include
#include
#include
#define ll long long
using namespace std;
const int maxn=2505;
int n,m;
struct cows{
	int minx;
	int maxx;
	cows(int u,int v):minx(u),maxx(v){}
};
bool cmp1(cows x1,cows x2){
	return x1.minx>x2.minx;
}
bool cmp2(int x1,int x2){
	return x1>x2;
}
vector<cows> a;
vector<int> b;
int ans; 
int main(){
	
	cin>>n>>m;
	int u,v;
	for(int i=0;i<n;i++){
		cin>>u>>v;
		a.push_back(cows(u,v));
	}
	sort(a.begin(),a.end(),cmp1);
	for(int i=0;i<m;i++){
		cin>>u>>v;
		for(int j=0;j<v;j++) b.push_back(u);
	}
	sort(b.begin(),b.end(),cmp2);
	int len=b.size();
	for(int i=0;i<n;i++){                    //针对每一头牛 
		for(int j=0;j<len;j++){
		  if(b[j]>=a[i].minx && b[j]<=a[i].maxx){
		  	ans++;
		  	b[j]=-1;
		  	break;
			}
		} 
	}
	cout<<ans;
	return 0;
	
} 

你可能感兴趣的:(贪心,《算法竞赛进阶指南》)