NYOJ 891,287,12 , 14 ,966贪心 区间问题
2014-04-18 23:51
567 查看
NYOJ 891 找点
给一定区间,取最小点覆盖所有区间。
逆序:先左排升序,再右排
正序:先右排升序,再左排
题意:取最小覆盖岛屿的雷达数目
转换:将岛屿映射到坐标轴上,p->[a,b]区间 ,[a,b]表示可以覆盖p的范围。
类:NYOJ 891 找点
右排:
左排:
左排:
右排:
NYOJ 14 会场安排&966 选择不相交区间
排序:右排
先对end升序,再对begin降序
end升序排列,保证结束时间最小,begin较大,尽量在end一样的情况下,保证开始时间越大。
对begin进行降序排列,可减少运行时间。
左排:
#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))
a392
{
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;
}
。
给一定区间,取最小点覆盖所有区间。
逆序:先左排升序,再右排
#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))
a392
{
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;
}
。
相关文章推荐
- 基于贪心算法的几类区间覆盖问题 nyoj 12喷水装置(二) nyoj 14会场安排问题
- nyoj 891 找点 贪心 区间选点问题
- NYOJ-14 会场安排问题(贪心 区间覆盖)
- NYOJ 12 喷水装置(2)贪心之区间覆盖问题
- nyoj--12--喷水装置(二)(区间覆盖问题+贪心)
- nyoj--12--喷水装置(二)(区间覆盖问题+贪心)
- nyoj 891 找点(贪心,区间选点问题)
- POJ 1328 && NYOJ 891 - 贪心 区间选点问题
- nyoj 14 会场安排问题 (贪心(时间区间))
- NYOJ 14 会场安排问题(经典题目,贪心,区间问题)
- 【贪心】[区间覆盖]nyoj12
- nyoj14会场安排问题【贪心】~
- NYOJ891. 找点(贪心+区间选点问题)
- NYOJ 891 找点 (贪心&区间选点)
- NYOJ 14 会场安排问题(选择不相交区间)
- 喷水装置(二)(南阳oj12)(贪心之区间覆盖问题)
- Num 25 : NYOJ0014 会场安排问题 + HDOJ2037:今年暑假不AC [ 贪心 ][ 选择不相交区间 ]
- NYOJ 12 喷水装置(二)(区间问题)
- NYOJ 287 Radar 贪心之 区间选点
- nyoj14会场安排问题VS hdoj2037今年暑假不AC(贪心之时间安排问题)