NYOJ 891,287,12 , 14 ,966贪心 区间问题

NYOJ   891   找点

给一定区间,取最小点覆盖所有区间。

逆序:先左排升序,再右排

 
#include <stdio.h>
#include <algorithm>
using namespace std;
typedef struct N{
  int a,b;
}Data[100];
bool cmp(N x,N y)
{
    if(x.a!=y.a)
        return x.a<y.a;
    return x.b<y.b;
}
Data data;
int main()
{
    int n,i,j,t,k,m;
    while(~scanf("%d",&n))
    {
        for(i=0;i<n;i++)
        scanf("%d %d",&data[i].a,&data[i].b);
        sort(data,data+n,cmp);
        m=1;
        for(i=n-1,j=n-1-1;j>=0;)
        {
            if(data[j].b<data[i].a)
            {
                i=j;
                m++;
            }
            j--;
        }
        printf("%d\n",m);
        }
    return 0;
}
        

正序:排升序,再左排

 
#include<stdio.h>
#include<stdlib.h>
struct node{
  int x;
  int y;
};
struct node a[100];
int cmp(const void *a,const void *b)
{
    struct node *c=(node *)a;
    struct node *d=(node *)b;
    if(c->y!=d->y) return c->y-d->y;
       else return d->x-c->x;
}
int main(){
  int n,i,j,temp;
  while(scanf("%d",&n)!=EOF){
   for(i=0;i<n;i++)
      scanf("%d%d",&a[i].x,&a[i].y);
   qsort(a,n,sizeof(a[0]),cmp);
   temp=a[0].y;
   int count=1;
   for(i=1;i<n;i++){
    if(a[i].x>temp){
        count++;
        temp=a[i].y;
    }
   }
   printf("%d\n",count);
  }
  return 0;
}
        
NYOJ 287 Radar

题意:取最小覆盖岛屿的雷达数目

转换:将岛屿映射到坐标轴上,p->[a,b]区间 ,[a,b]表示可以覆盖p的范围。

类:NYOJ 891 找点

右排:

 
#include<stdio.h>
#include<math.h>
#include<algorithm>
using namespace std;
const int MAXN=1005;
struct Line
{
    double l,r;
}line[MAXN];//每个岛作半径为d的圆,截得区间
bool cmp(Line a,Line b)
{
    return a.r<b.r;
}
int main()
{
    int n,d;
    int i;
    int x,y;
    int num=1,flag,count;
    while(scanf("%d %d",&n,&d)&&n&&d)
    {
        flag=1;
        for(i=0;i<n;i++)
        {
            scanf("%d %d",&x,&y);
            if(!flag) continue;
            if(y<=d){
              line[i].l=(double)x-sqrt((double)d*d-y*y);
               line[i].r=(double)x+sqrt((double)d*d-y*y);
            }else flag=0;
        }
        if(!flag)
        {
            printf("Case %d: -1\n",num++);
            continue;
        }
        sort(line,line+n,cmp);
        count=1;
        double now=line[0].r;
        for(i=1;i<n;i++)
        {

            if(line[i].l<=now+0.00005) continue;
            now=line[i].r;
            count++;
        }
      printf("Case %d: %d\n",num++,count);
    }
    return 0;
}

左排:

#include <iostream>
#include <cmath>
#include <algorithm>
using namespace std;

int n, d;
typedef struct {
	double left, right;
}Point;
Point islands[1000];

bool compare(Point a, Point b)
{
	return (a.left-b.left) < 10e-7;
}

int greedy()
{	//贪心法计算最小需要的radar数
	int ans = 1;
	double pre = islands[0].right;	//前一radar的位置
	for(int i = 1; i < n; i++) {
		if(islands[i].left-pre > 10e-7) {
			ans++;
			pre = islands[i].right;
		} else {
			if(islands[i].right-pre < 10e-7)
				pre = islands[i].right;
		}
	}
	return ans;
}

int main() 
{
	int cas = 0, x, y;
	while(scanf("%d%d", &n, &d) != EOF) {
		if(!n && !d)
			break;
		bool impossible = false;
		for(int i = 0; i < n; i++) {
			scanf("%d%d", &x, &y);
			if(!impossible && (y <= d)) {
				double tmp = sqrt(double(d*d-y*y));
				islands[i].left = x-tmp;
				islands[i].right = x+tmp;
			}
			else
				impossible = true;
		}
		if(impossible) {
			printf("Case %d: -1\n", ++cas);
			continue;
		}
		sort(islands, islands+n, compare);//将island按左端点left由小到大排序

		printf("Case %d: %d\n", ++cas,greedy());
	}
	return 0;
}
NYOJ 12喷水装置(二)

左排:

 
#include<stdio.h>
#include<string.h>
#include<math.h>
#include<algorithm>
using namespace std;
struct ps
{
    double left;
    double right;
}w[10001];
bool comp(ps a,ps b)//按照左交点的大小进行排序
{
    if(a.left<b.left) return true;
    return false;
}
int main()
{
    int ncases,n,i,width,high,x,r,count,flag;
    double len,sum,max;
    scanf("%d",&ncases);
    while(ncases--)
    {
        flag=1;sum=0;count=0;
        scanf("%d %d %d",&n,&width,&high);
        for(i=0;i<=n-1;i++)
        {
            scanf("%d %d",&x,&r);
            len=(double)r*r-(double)high/2*high/2;
            if(len>=0) {len=sqrt(len);}
            if(len<0) {len=0;}//覆盖不到,这个长度就可以忽略掉
            w[i].left=x-len;
            w[i].right=x+len;
        }
        sort(w,w+n,comp);
        while(sum<width)//关键
        {
            max=0;//代表比前一个装置能够辐射的范围往右延长的最大值
            for(i=0;i<=n-1&&w[i].left<=sum;i++)//w[i].left<=sum保证两个碰水装置可以相交,
                                               //也就是说两点直接的能够完全覆盖
            {
                if((w[i].right-sum)>max)//找出既能保证完全覆盖又能保证这点能够达到的右交点最大,即需要的喷水装置最少
                {
                    max=w[i].right-sum;//找出最大值
                }
            }
            if(max==0)//说明w[i].left>sum,表示其中一个点的右交点跟另外一个点的左交点没有连接上,即不能完全覆盖
            {
                flag=0;
                break;
            }
            else
            {
                sum=sum+max;//更新能够覆盖的宽度
                count++;
            }
        }
        if(flag==1)
        {
            printf("%d\n",count);
        }
        else
        {
            printf("0\n");
        }
    }
    return 0;
}
     

 右排:
 
#include<stdio.h>
#include<stdlib.h>
#include<math.h>
typedef struct{
   int a;//左
   int b;//右
}A;
int cmp(const void *a,const void *b){//右排序
     return (*(A*)a).b-(*(A*)b).b;  //升序
}
int main()
{
     int N,n,w,h,i,j,x,r,count,len;
     A d[10000];
     scanf("%d",&N);
     while(N--){
          scanf("%d %d %d",&n,&w,&h);
          for(i=0,j=0;i<n;i++){
             scanf("%d %d",&x,&r);
             if(r>h/2){
                d[j].a=x-sqrt(r*r-h*h*1.0/4);
                d[j].b=x+sqrt(r*r-h*h*1.0/4);
                j++;//去掉不符合条件的
             }
           }
          n=j;
          qsort(d,n,sizeof(A),cmp);
          count=0;len=0;j=-1;
          while(len<w){
               for(i=n-1;i>j;i--)
               if(d[i].a<=len)
                    len=d[i].b,count++,j=i;
               if(i==j) break;
          }
          if(len>=w) printf("%d\n",count);
          else printf("0\n");
       }
}
                

NYOJ 14 会场安排&966 选择不相交区间

排序:右排

先对end升序,再对begin降序

end升序排列,保证结束时间最小,begin较大,尽量在end一样的情况下,保证开始时间越大。

对begin进行降序排列,可减少运行时间。


 
#include<stdio.h>
#include<string.h>
 #include<iostream>
 #include<algorithm>
 using namespace std;
 struct node
 {
 int start;
 int end;
 }s[10003];
 bool cmp(node x,node y)
 {
 if(x.end==y.end)
 return x.start>y.start;//降序
 return x.end<y.end;//升序
 }
 int main()
 {
     int test,num,n,flag,i;
     scanf("%d",&test);
     while(test--)
     {
         num = 1;
         scanf("%d",&n);
         for(i=0;i<n;i++)
         scanf("%d%d",&s[i].start,&s[i].end);
         sort(s,s+n,cmp);
         flag = s[0].end;
         for(i=1;i<n;i++)
         if(s[i].start>flag)
         {
         num ++;
         flag = s[i].end;
         }
     printf("%d\n",num);

    }
 return 0;
 }
        

左排:

#include<stdio.h>
#include<algorithm>
using namespace std;
struct ac
{
    int begin;
    int end;
};
bool cmp(ac x,ac y)
{
    return x.begin<y.begin;
}
int main()
{
    int n,d=1;
    while(~scanf("%d",&n))
    {
        int a,b;
        ac fun[1005];
        for(int i=0;i<n;i++)
        {
            scanf("%d%d",&a,&b);
            if(a>b)
                swap(a,b);
            fun[i].begin=a;
            fun[i].end=b;
        }
        sort(fun,fun+n,cmp);
        int start=fun[n-1].begin,cnt=1;
        for(int i=n-2;i>=0;i--)
        {
            if(fun[i].end<start)//关键
            {
                cnt++;
                start=fun[i].begin;
            }
        }
        printf("Case %d:\n",d++);
        printf("%d.\n",cnt);
    }
    return 0;
}
。



评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值