zoukankan      html  css  js  c++  java
  • 几类区间覆盖

    一、区间完全覆盖

    Description:给定区间,和n的线段,要求选择最少的线段使给定区间完全覆盖

    Solution: 贪心,先根据左端点从小到大排序,先确定一个答案区间,然后在没有选择的线段中选择一个左端点在答案区间中,右端点最大的加入答案区间

    <1>Code[poj2376]:
    #include<cstdio>
    #include<cstring>
    #include<iostream>
    #include<algorithm>
    using namespace std;
    const int MAXX=25010;
    struct node
    {
    	int l,r;
    	node(){
    		l=r=0;
    	}
    }t[MAXX];
    int n,m;
    inline bool cmp(node A,node B){
    	return A.l<B.l;
    }
    int main(){
       scanf("%d%d",&n,&m);
       int num=n;
       for(int i=1;i<=n;++i){
        int x,y;
       	scanf("%d%d",&x,&y);
        if(x>m){
        	num--;
        	continue;}
        t[i].l=x;
        t[i].r=y;
       }
       sort(t+1,t+n+1,cmp);
       int pos,rr,cnt;
       pos=rr=1;
       cnt=0;
       while(rr<=m&&pos<=num){
       	int rmax=0;
       	  while(t[pos].l<=rr&&pos<=num){
       	  	rmax=max(rmax,t[pos].r);
       	  	++pos;
       	  }
       	  cnt++;
       	  if(rmax+1<=rr)break;
       	  rr=rmax+1;
       }
       if(rr>m)cout<<cnt;
       else cout<<-1;
       return 0;
    }
    /*
    2 5
    2 4
    3 5
    */
    
    <2>Code[UVA10382]:
    #include<cstdio>
    #include<iostream>
    #include<cstring>
    #include<cmath>
    #include<algorithm>
    using namespace std;
    const int MAXX=10010;
    struct node{
    	double l,r;
    	node(){
    		l=r=0;
    	}
    }t[MAXX];
    double w,h;
    int n,tot,T; 
    inline bool cmp(node A,node B){
    	return A.l<B.l;
    }
    int main(){
       while(scanf("%d%lf%lf",&n,&w,&h)!=EOF){
       	tot=0;
       	for(int j=1;j<=n;++j){
       		double p,r;
       		cin>>p>>r;
       		if(r*r-h*h/4.0<0.0)continue;
       		t[++tot].l=p-sqrt(r*r-h*h/4.0);
       		t[tot].r=p+sqrt(r*r-h*h/4.0);
       	}
       	sort(t+1,t+tot+1,cmp);
       	double rr;
       	int pos=1;
       	int ans=0;
       	rr=0.0;
        while(rr<w&&pos<=tot){
          double rmax=0;
          while(pos<=tot&&t[pos].l<=rr){
          	   rmax=max(rmax,t[pos].r);
               ++pos;
            }
            ans++;
            if(rmax<=rr)break;//不加这句话会死循环,因为可能无解
            rr=rmax;
         }
         if(rr>=w)cout<<ans<<endl;
         else cout<<-1<<endl;
       }
    }
    
    <3>Code[lougu1514]引水入城
    // luogu-judger-enable-o2
    #include<cstdio>
    #include<cstring>
    #include<iostream>
    #include<queue>
    #include<algorithm>
    using namespace std;
    const int MAXX=1000;
    int map[MAXX][MAXX];
    int dx[4]={0,0,-1,1};
    int dy[4]={1,-1,0,0};
    bool vis[MAXX][MAXX];
    bool v[MAXX];
    int n,m,num;
    struct node{
        int l,r;
        node(){
            l=r=0;
        }
    }t[MAXX];
    inline bool cmp(node A,node B){
        return A.l<B.l;
    }
    inline bool check(int x){
        memset(vis,0,sizeof(vis));
        queue<pair<int ,int > >q;
        vis[n][x]=1;
        pair<int ,int >s=make_pair(n,x);
        q.push(s);
        while(q.size()){
            pair<int ,int > t=q.front();
            int x=t.first;
            int y=t.second;
            q.pop();
            for(int i=0;i<4;++i){
            	int xx=x+dx[i];
            	int yy=y+dy[i];
            	if(xx>n||xx<1||yy>m||yy<1||vis[xx][yy]||map[xx][yy]<=map[x][y])continue;
            	vis[xx][yy]=1;
            	pair<int ,int >e=make_pair(xx,yy);
                q.push(e);
            }
        }
        for(int i=1;i<=m;++i)if(vis[1][i])return 1;
        return 0;
    }//判是否有解
    inline void bfs(int x){
        memset(vis,0,sizeof(vis));
        queue<pair<int ,int > >q;
        vis[1][x]=1;
        pair<int,int >s=make_pair(1,x);
        q.push(s);
        while(q.size()){
        	pair<int ,int> t=q.front();
        	int x=t.first;
        	int y=t.second;
        	q.pop();
        	for(int i=0;i<4;++i){
        	    int xx=x+dx[i];
            	int yy=y+dy[i];
            	if(xx>n||xx<1||yy>m||yy<1||vis[xx][yy]||map[xx][yy]>=map[x][y])continue;
            	vis[xx][yy]=1;
            	pair<int ,int >e=make_pair(xx,yy);
                q.push(e);
        	}
        }
        bool flag=0;
        int len=0;
        for(int i=1;i<=m;++i){
        	if(vis[n][i]==1){
                len++;
        		if(flag)continue;
        		t[x].l=i;
        		flag=1;
        	}
        }
        t[x].r=t[x].l+len-1;
    } 
    inline void solve(){
        sort(t+1,t+m+1,cmp);
        int pos,rr;
        int ans=0;
        rr=pos=1;
        while(rr<=m){
           int rmax=0;
           while(t[pos].l<=rr){
           	rmax=max(rmax,t[pos].r);
           	++pos;
           }
           rr=rmax+1;
           ans++;
        }
        cout<<1<<endl<<ans;
    }//不需要特判,因为一定有解
    int main(){
       cin>>n>>m;
       for(int i=1;i<=n;++i)
       	 for(int j=1;j<=m;++j)
            scanf("%d",&map[i][j]);
       for(int i=1;i<=m;++i){
       	v[i]=check(i);
       	num+=v[i];
       }
       if(num!=m)cout<<0<<endl<<m-num<<endl;
       else {
       	for(int i=1;i<=m;++i)bfs(i);
       	solve();
       }
       return 0;
    }
    

    我对于以上三个题有一些思考:

    (1).例题一和三,都是整数的区间,但是因为三我处理的状态是一定有解的我们不需要特判,如果没有解我们也不特判,就会无限循环

    (2)例题二是实数的,而其他两道题是整数的,对于我们确定的rr,我们待选的l可以是rr+1,所以更新时是rr=rmax+1,但是实数域就不可以了只能rr=rmax

    二、最大不相交覆盖

    Description:给定一个区间,和n个线段,求在这个区间不相交的线段最多有多少个

    Solution:根据右端点从小到大排序,按顺序处理每个区间,如果有相同的右端点,取左端点最大的

    例题:[NYOJ1014会场安排问题]

    裸题
    Code
    #include<cstdio>
    #include<cstring>
    #include<iostream>
    #include<cstdlib>
    #include<cmath>
    #include<algorithm>
    using namespace std;
    const int MAXX=10010;
    struct node{
    	int l,r;
    	node(){
    		l=r=0;
    	}
    }t[MAXX];
    int n,T;
    inline bool cmp(node A,node B){
    	if(A.r<B.r)return 1;
    	else if(A.r==B.r)return A.l>B.l;
        else return 0;
    }
    int main(){
        cin>>T;
        for(int i=1;i<=T;++i){
        	cin>>n;
        	for(int j=1;j<=n;++j)cin>>t[j].l>>t[j].r;
        	sort(t+1,t+n+1,cmp);
            int lastr=0; 
            int ans=0;
            for(int j=1;j<=n;++j){
                if(t[j].l>=lastr+1){
                	lastr=t[j].r;
                	ans++;
                }
            }
            cout<<ans<<endl;
        }
        return 0;
    }
    
  • 相关阅读:
    MIne FirstBlog
    P6563 [SBCOI2020]一直在你身旁
    P6563 [SBCOI2020]一直在你身旁
    T122085 [SBCOI2020]时光的流逝
    LC 918. Maximum Sum Circular Subarray
    1026 Table Tennis
    LC 1442. Count Triplets That Can Form Two Arrays of Equal XOR
    LC 1316. Distinct Echo Substrings
    LC 493. Reverse Pairs
    1029 Median (二分)
  • 原文地址:https://www.cnblogs.com/ARTlover/p/9552105.html
Copyright © 2011-2022 走看看