1020贪心练习

1.P1230智力大冲浪

思路:赢取最多的钱,即扣掉的钱最少。等价于m先减去所有的wi,再计算最大得分。对于时段x我们可以做时限ti>=x的游戏。所以从后往前枚举时段i,把时限ti>=i的游戏的wi放入一个大根堆,每一时段m加上堆顶值。注意中间可能空堆。

const int maxn=505;
struct node{int t,w;}e[maxn];
bool cmp(node a,node b){return a.t<b.t;}
priority_queue<int>q;
int main(){
    int m=read(),n=read(),maxx=0;
    for(int i=1;i<=n;i++)e[i].t=read(),maxx=max(maxx,e[i].t);
    for(int i=1;i<=n;i++)e[i].w=read(),m-=e[i].w,q.push(0);
    sort(e+1,e+1+n,cmp);int now=n;
    for(int i=maxx;i>=1;i--){
        while(e[now].t>=i)q.push(e[now].w),now--;
        m+=q.top();q.pop();
    }
    if(m<0)printf("0
");
    else printf("%d
",m);
    return 0;
}

2.整数区间

我们定义一个整数区间[a,b]:是一个从a开始至b结束的连续整数的集合。
编一个程序,对给定的 n(n≤1000)个区间,找出满足下述条件的所含元素个数最少的集合中元素的个数:对于所给定的每一个区间,都至少有两个不同的整数属于该集合。

解法1:差分约束。之前写过了。
解法2:题意即从每个区间选至少两个点,使选点总数最小。按照左端点从大到小枚举区间,则若此区间没选满两个点,优先选择靠左的点一定最优。

const int maxn=10005;
struct node{int l,r;}a[maxn];
bool cmp(node a,node b){return a.l>b.l;}
int vis[maxn],ans;
int main(){
	int n=read();
	for(int i=1;i<=n;i++)a[i].l=read(),a[i].r=read();
	sort(a+1,a+1+n,cmp);
	for(int i=1;i<=n;i++){
		int tot=0;
		for(int j=a[i].l;j<=a[i].r;j++)
			if(vis[j])tot++;
		if(tot==0)ans+=2,vis[a[i].l]=vis[a[i].l+1]=1;
		else if(tot==1)ans++,vis[a[i].l]=1;
	}
	printf("%d
",ans);
	return 0;
}

3.活动选择

线段覆盖板子,按右端点排序,能选的优先选右端点较小的。

const int maxn=1005;
struct node{
    int l,r;
}p[maxn];
bool cmp(node a,node b){
    if(a.r==b.r)return a.l>b.l;
    return a.r<b.r;
}
int main(){
        int k=read(),cnt=0,tmp=0;
        for(int i=1;i<=k;i++){
            //int a=read();
            p[i].l=read();
            p[i].r=read();
        }
        sort(p+1,p+1+k,cmp);
        for(int i=1;i<=k;++i){
            if(p[i].l>=tmp){
                cnt++;
                tmp=p[i].r;
            }
        }
        printf("%d
",cnt);
    return 0;
}

4.P1325 雷达安装
雷达显然都建在海岸线上更优。算出每个岛被覆盖的雷达位置区间,使每个区间里至少有一个点。

const int maxn=1005;
int x[maxn],y[maxn];
struct node{double l,r;}p[maxn];
bool cmp(node a,node b){return a.r<b.r;}
int main(){
	int n=read(),d=read(),ans=1;
	for(int i=1;i<=n;i++){
		scanf("%d%d",&x[i],&y[i]);
		if(y[i]>d){
			printf("-1
");
			return 0;
		}
		double dt=sqrt(d*d-y[i]*y[i]);
		p[i].l=x[i]-dt;p[i].r=x[i]+dt;
	}
	sort(p+1,p+1+n,cmp);
	double tmp=p[1].r;
	for(int i=2;i<=n;i++)if(p[i].l>tmp)ans++,tmp=p[i].r;
	printf("%d
",ans);
	return 0;
}
原文地址:https://www.cnblogs.com/zdxx/p/13847322.html