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;
    }
    
  • 相关阅读:
    Mysql查询语句,select,inner/left/right join on,group by.....[例题及答案]
    Java IO实现文件(及文件夹)的复制 原创代码【精】
    [精华帖]Java接口怎么定义?如何使用?【实例讲解】
    Java面向对象中this关键字详解 意义+实例讲解【hot】
    linux系统编程之进程(三):进程复制fork,孤儿进程,僵尸进程
    linux系统编程之进程(二):进程生命周期与PCB(进程控制块)
    linux系统编程之进程(一):进程与程序
    linux系统编程之文件与IO(八):文件描述符相关操作-dup,dup2,fcntl
    linux系统编程之文件与IO(七):时间函数小结
    linux系统编程之文件与IO(六):实现ls -l功能
  • 原文地址:https://www.cnblogs.com/ARTlover/p/9552105.html
Copyright © 2011-2022 走看看