http://poj.org/problem?id=3614
题意
有C个奶牛去晒太阳 (1 <=C <= 2500),每个奶牛各自能够忍受的阳光强度有一个最小值和一个最大值,太大就晒伤了,太小奶牛没感觉。
而刚开始的阳光的强度非常大,奶牛都承受不住,然后奶牛就得涂抹防晒霜,防晒霜的作用是让阳光照在身上的阳光强度固定为某个值。
那么为了不让奶牛烫伤,又不会没有效果。
给出了L种防晒霜。每种的数量和固定的阳光强度也给出来了
每个奶牛只能抹一瓶防晒霜,最后问能够享受晒太阳的奶牛最多有几个。
分析:
设C个奶牛的防晒区间分别为 (L1,R1) ( L2 , R2 ) ( L3 ,R3) ……( Ln ,Rn) ,L 种防晒霜(SPF1, num1) (SPF2,num2) …… (SPFn, num n)
①要想使尽可能多的奶牛能够享受阳光, 主要取决于防晒霜,应尽量使防晒霜SPF小的应用于防晒区间小的,并且在SPF,num值允许的情况下尽量涉及到每个区间,才是最佳的
②将C个奶牛的防晒区间按照左端点从小到大的顺序排序,左端点相同的按照右端点从小到大排序,将L种防晒霜按照防晒系数SPF从小到大排序
③从小到大遍历每种防晒霜,针对防晒霜Li ,首先确定能够被其作用的奶牛区间,即满足条件 L <= Li. SPF<=R d的奶牛区间 ,在这些区间当中优先选择R最小的那个区间,因为大区间(R比较大)的奶牛有更大的选择空间,而R小的能选择的空间比较小,让其优先使用防晒霜。这样就能保证整个过程尽可能多的奶牛使用合适的防晒霜。
#include <iostream>
#include <algorithm>
#include <cstring>
using namespace std;
struct Node
{
int left,right;
bool operator<(Node b)
{
if(left!=b.left) return left<b.left;
else return right<b.right;
}
};
struct Tode
{
int value,num;
bool operator<(Tode b)
{
return value<b.value;
}
};
Node p[2550];
Tode q[2550];
int C,L;
int vis[2550];
void solve()
{
long long Count=0,pos;
memset(vis,0,sizeof(vis));
for(int i=0;i<L;) //遍历每种防晒霜
{
if(q[i].num>=1) //判断该种防晒霜个数是否用完
{
int Min=999999;
for(int j=0;j<C;j++) //遍历每个奶牛
{
if(vis[j]==0&&q[i].value>=p[j].left&&p[j].right>=q[i].value)
//判断奶牛是否使用过防晒霜(vis[i]==0) 判断区间用是否能用该防晒霜
{
if(p[j].right<Min) //在满足条件的区间中选出 右端点最小的 使用该防晒霜
{
Min=p[j].right;
pos=j; //记录该区间的位置
}
}
else if(p[j].left>q[i].value) break; //已经排好序,一旦左端点大于value,后面的都>value
}
if(Min!=999999) //判断是否还有适合该种防晒霜奶牛区间
{
Count++,vis[pos]=1;//让合适区间中右端点最小的使用
q[i].num--; //该种防晒霜的个数-1
}
else i++; //没有适合该种防晒霜的,跳到下一种防晒霜
}
else i++; //该种防晒霜用完了,跳到下一种防晒霜
if(Count==C) break; //覆盖到所有的奶牛,不用再遍历防晒霜了,跳出
}
cout<<Count<<endl;
}
int main()
{
cin>>C>>L;
for(int i=0;i<C;i++)
cin>>p[i].left>>p[i].right;
for(int i=0;i<L;i++)
cin>>q[i].value>>q[i].num;
sort(p,p+C);
sort(q,q+L);
solve();
return 0;
}