zoukankan      html  css  js  c++  java
  • 20201020 day40 复习9:贪心综合练习(二)

    艰苦卓绝的做题过程x2

    1 怎么看电影&zdx看电影&活动安排

    注:“怎么看电影”和“活动安排”是同一个题,由于洛谷没有该题,故使用了之前自己上传的题目。“zdx看电影”是多组数据,每组数据中做法相同。

    problem

    (n)个活动,分别有起止时间([x,y)),两个活动([a,b),[c,d))不想交,则叫做这两个活动相容。求这(n)个活动中互相相容的活动个数最大值。

    solution

    贪心考察。把所有的活动起止时间映射在数轴上,我们可以选择结束时间尽可能早的点,这样可以继续选择更早开始的活动,使得全局更优。代码实现显然,复杂度(O(n)),多组数据(O(Tn))

    thoughts

    debug:t1写成t。
    100pts:贪心。

    code

    活动安排&怎么看电影

    #include <cstdio>
    #include <algorithm>
    #include <cmath>
    #include <cstring>
    #include <iostream>
    #include <queue>
    using namespace std;
    int read() {
        long long a = 0, op = 1;
        char c = getchar();
        while (c > '9' || c < '0') {
            if (c == '-')
                op = -1;
            c = getchar();
        }
        while (c >= '0' && c <= '9') {
            a *= 10, a += c ^ 48, c = getchar();
        }
        return a * op;
    }
    struct node {
        int num, l, r;
    } a[1000005];
    int t;
    int k;
    bool cmp1(node x, node y) { return x.r < y.r; }
    int ans = 1, t1;
    int main() {
        k = read();
        for (int i = 1; i <= k; i++) a[i].l = read(), a[i].r = read();
        sort(a + 1, a + k + 1, cmp1);
        t1 = a[1].r;
        for (int i = 2; i <= k; i++)
            if (a[i].l >= t1)
                ans++, t1 = a[i].r;
        printf("%d
    ", ans);
        return 0;
    }
    

    zdx看电影(多组数据)

    #include <cstdio>
    #include <algorithm>
    #include <cmath>
    #include <cstring>
    #include <iostream>
    #include <queue>
    using namespace std;
    int read(){
    	long long a=0,op=1;char c=getchar();
    	while(c>'9'||c<'0') {if(c=='-') op=-1;c=getchar();}
    	while(c>='0'&&c<='9'){a*=10,a+=c^48,c=getchar();}
    	return a*op;
    }
    struct node {
    	int num,l,r;
    }a[1000005];
    int t;
    int k;
    bool cmp1(node x,node y){
    	return x.r<y.r;
    }
    int main(){
    	t=read();
    	while(t--){
    		k=read();
    		for(int i=1;i<=k;i++) a[i].num=read(),a[i].l=read(),a[i].r=read();
    		//for(int i=1;i<=k;i++) printf("test:%d %d
    ",a[i].l,a[i].r);
    		sort(a+1,a+k+1,cmp1);
    		//for(int i=1;i<=k;i++) printf("testxxx:%d %d
    ",a[i].l,a[i].r);
    		int t1=a[1].r,ans=1;
    		for(int i=2;i<=k;i++) 
    			if(a[i].l>=t1) ans++,t1=a[i].r;
    		printf("%d
    ",ans);
    		for(int i=1;i<=k;i++) a[i].l=0,a[i].r=0;
    	}
    	return 0;
    }
    
    

    2 智力大冲浪

    problem

    (n)个活动,每个活动没有完成扣除的金额为(p_i),每个活动的完成时限为(q_i),在完成时限内没有完成会扣除相应金额。给定金额(m),求剩余的钱的最大值。

    solution

    如果遇到一个时限为(k)的活动,我们要尽可能的把它放到能放的(le k)的位置。如果不能放,我们就把他放到最大的一个空时间段,这样避免影响之后的结果,也不会对结果产生影响,因为如果这件事情做不完,在任何情况下做不完扣除的钱都一样。

    thoughts

    100pts:一次AC。

    code

    #include <cstdio>
    #include <algorithm>
    #include <cmath>
    #include <cstring>
    #include <iostream>
    #include <queue>
    using namespace std;
    int read(){
    	long long a=0,op=1;char c=getchar();
    	while(c>'9'||c<'0') {if(c=='-') op=-1;c=getchar();}
    	while(c>='0'&&c<='9'){a*=10,a+=c^48,c=getchar();}
    	return a*op;
    }
    int tim[505],n,s,x,mon[505],m;
    struct node{
    	int tim,mon;
    }a[505];
    int done[505];
    bool cmp1(node x,node y){
    	return x.mon>y.mon;
    }
    int main(){
    	m=read();n=read();
    	for(int i=1;i<=n;i++) a[i].tim=read();
    	for(int i=1;i<=n;i++) a[i].mon=read();
    	sort(a+1,a+n+1,cmp1);
    	for(int i=1;i<=n;i++){
    	 	x=1;
    		for(int j=a[i].tim;j>=1;j--){
    			if(done[j]==0) {x=0,done[j]=1;break;}
    		}
    		if(x){
    			for(int k=n;k>=1;k--) 
    				if(done[k]==0) {done[k]=1;break;}
    			s+=a[i].mon;
    		}
    	}
    	printf("%d",m-s);
    	return 0;
    }
    
    

    3 雷达安装

    problem

    平面直角坐标系中,第I、II象限内有(n)个点,在(x)轴上寻找最少的(k)个点,使得以它们为圆心,(d)为半径的圆将所有的点覆盖。

    solution

    以每个点为圆心,d为半径做圆,每个点可以在(x)轴上得到一个区间,这样就转换成了在(x)轴上选点,使得每个区间内都至少有一个点。
    我们按照右端点排序,如果下一个区间的右端点在前一个里面,我们可以跳过,否则我们就选择右端点最旁边的那个点(也就是那个点),显然这样更优。复杂度(O(n))

    thoughts

    100pts:一次AC。

    code

    #include <cstdio>
    #include <algorithm>
    #include <cmath>
    #include <cstring>
    #include <iostream>
    #include <queue>
    using namespace std;
    int read(){
    	long long a=0,op=1;char c=getchar();
    	while(c>'9'||c<'0') {if(c=='-') op=-1;c=getchar();}
    	while(c>='0'&&c<='9'){a*=10,a+=c^48,c=getchar();}
    	return a*op;
    }
    const int maxn=1e4+5;
    int n,d,ans,x[maxn],y[maxn];
    double l[maxn],r[maxn],temp;
    struct node{
    	double l,r;
    }a[maxn];
    double cmp(node a,node b){return a.r<b.r;}
    int main(){
    	n=read(),d=read();
    	for(int i=1;i<=n;i++) x[i]=read(),y[i]=read();
    	for(int i=1;i<=n;i++) 
    		a[i].l=x[i]-sqrt(d*d-y[i]*y[i]),
    		a[i].r=x[i]+sqrt(d*d-y[i]*y[i]);
    	sort(a+1,a+n+1,cmp);
    	for(int i=1;i<=n;i++){
    		if(i==1) temp=a[i].r,ans++;
    		else{
    			if(temp>=a[i].l) continue;
    			else ans++,temp=a[i].r;
    		}
    	}
    	printf("%d",ans);
    	return 0;
    }
    

    4 整数区间

    problem

    给定(n)个区间([a_i,b_i]),选择最少的点,使得每个区间内至少有两个点,求选择点的个数。

    solution

    把区间先按右端点从小到大排序,开两个变量来记录位置(保证x < y)
    如果区间右端点大于y,则这个区间者少有两个数被劝进集合中了,continue掉就好了
    如果区间的右端点在x和y之间,把x变成y,y变成这个区间的左端点,同时ans++
    如果区间的右端点小于x,x变成区间的左端点,y变成区间的右端点,同时ans+=2

    thoughts

    100pts:一次AC。

    code

    #include<iostream>
    #include<cstdio>
    #include<algorithm>
    using namespace std;
    struct node{
        int a;
        int b;
    };
    node m[1000];
    bool cmp(node a,node b)
    {
        if(a.a != b.a)
        {
            return a.a < b.a;
        }
        else
        return a.b < b.b;
    }
    int main()
    {
        int n,f1,f2,tot = 0;
        cin>>n;
        for(int i = 1;i <= n;i++)
        {
            cin>>m[i].a>>m[i].b;
        }
        sort(m + 1,m + n + 1,cmp);
        f1 = m[n].a;
        f2 = m[n].a + 1;
        tot += 2;
        for(int i = n - 1;i > 0;i--)
        {
            if(m[i].b < f1)
            {
                tot += 2;
                f1 = m[i].a;
                f2 = f1 + 1;
            }
            else if(m[i].b < f2) 
            {
                tot ++;
                f2 = f1;
                f1 = m[i].a;
            }
        }
        cout<<tot<<endl;
        return 0;
    }
    
  • 相关阅读:
    命令返回值
    PowerShell脚本传递参数
    HTTP 错误 404.3
    xcopy拷贝判断是否成功 robocopy排除子目录
    WinRAR压缩
    批处理命令随笔
    Android Studio3.0中dependencies依赖由compile变为implementation的区别
    compileSdkVersion, minSdkVersion 和 targetSdkVersion详解
    Android Studio工程Gradle编译报错
    rsync应用实例
  • 原文地址:https://www.cnblogs.com/liuziwen0224/p/20201020day40-001.html
Copyright © 2011-2022 走看看