题解 SP18965
题解 SP18965
题目大意:
奶牛很厌烦等待,奶牛i
在它的截止时间 $d_i( 1 \leq d_i \leq 10,000 ) $前挤 \(g(1\leq g_i\leq 1000)\)的奶,否则将不能挤奶。时间 t
开始时为 0
,即在时间 \(t=x\) 时,最多可以挤 x
头奶牛。
这个题目稍微读一下就会发现是一个贪心题
但是这个贪心思想应该怎么想呢?
首先,我们知道, 1
头奶牛,在 \(d_i\) 时间前都可以进行挤奶,这一点非常重要,这决定着两种不同的贪心策略,详情见后文
其次在同一时间,我们肯定是取最大值的,所以先对这里的 \(g_i\) 进行排序
接下来就是思考一下怎样才能取得在时限内,取得最大的牛奶价值呢?
我们已经按照价值由大到小排过序了,所以直接枚举 \([1,n]\) 内所有的牛奶即可
但是,我们还是没有触及到这道题的贪心策略
-
我们可以考虑,在当前时间,我们能得到的最大牛奶价值,这个最大值可以在输入时,直接将当前时间的桶存为当前时间的最大值
-
但是,这显然是错的,因为这里我们的牛奶价值,是可以在 \([1,d_i]\) 所有时间内获得的
-
单凭一个时间节点的值肯定是不行的,所以这是个错误的做法
下面我们来看一下正解
因为上面说过,牛奶在 \([1,d_i]\) 的区间内所有时间内都可以进行获取
所以,我们每次考虑,当前枚举到的时间之前有没有可以获取第 i
个牛奶的时间点
所以,我们的内层循环可以直接从当前枚举到的牛奶的时间往前扫一遍,如果有时间点并未被占用
我们就在此时间点进行第 i
个牛奶的获取,并且为此时间点打上标记
最终输出 ans
即可
#include<cstdio>
#include<vector>
#include<algorithm>
using namespace std;
const int N=2e5+10;
int n,tot,ans;
struct node{
int x,y;
}a[N];
int v[N],vis[N];
bool operator < (const node l,const node r){
return l.x>r.x;
}
int main(){
scanf("%d",&n);
for(int i=1;i<=n;i++){
scanf("%d%d",&a[i].x,&a[i].y);
}
sort(a+1,a+n+1);
for(int i=1;i<=n;i++){
for(int j=a[i].y;j>=1;j--){
if(vis[j]==0){
vis[j]=1;
ans+=a[i].x;
break;
}
}
}
printf("%d",ans);
return 0;
}