贪心小练

贪心:

 

1.poj 1922

 题意:一人从A地到B地,起始点时他要跟随第一个出发的人,之后如果有其他人追上初始他跟随的人时,
      他便跟随这些人,求其到达目的地的时间。
      首先考虑到这个时间应该等于他每次跟随其他人的各个时间总和,但是仔细的从总体思考,只需要算出他跟随的人到达目的地
      的时间,找出最小时间,即是正解,因为不管你中间跟随了谁,最终还是会跟随最快的人,和他一起到达目的地,花费时间最少。

View Code
 1 #include<iostream>
 2 #include<cstdio>
 3 #include<cstring>
 4 #include<cmath>
 5 
 6 using namespace std;
 7 
 8 int main()
 9 {
10     int n,v,t,ans;
11     double st;
12     while(scanf("%d",&n)!=EOF&&n)
13     {
14         ans=1<<30;
15         for(int i=0;i<n;i++)
16         {
17             scanf("%d%d",&v,&t);
18             if(t>=0)
19             {
20                 st=(4500*36)/(double)(v*10)+t;
21                 if(st-(int)st>0)
22                     st=(int)st+1;
23                 if(ans>st)
24                     ans=st;
25             }
26         }
27         printf("%d\n",ans);
28     }
29     return 0;
30 }

2.poj 2313

 题意:要求得B序列使得
      V = (|A(1)–B(1)|+ ...+|A(N)–B(N)|)+(|B(1)–B(2)|+...+|B(N-1)–B(N)|)最小
      简化一下式子 |Ai-Bi|+|Bi-Bi-1|+|Bi-Bi+1|最小,也就是在Ai,Bi-1,Bi+1三个点间找一点是的上式的值最小
      当然Bi=mid(Ai,Bi-1,Bi+1)这三个值的中间值,(1<i<n)即可保证V最小。

View Code
 1 #include<iostream>
 2 #include<cstdio>
 3 #include<cstdlib>
 4 #include<algorithm>
 5 #include<cstring>
 6 #include<cmath>
 7 
 8 using namespace std;
 9 
10 int cmp(int a,int b)
11 {
12     return a>b;
13 }
14 int mid(int a,int b,int c)
15 {
16     int mid[4];
17     mid[0]=a;mid[1]=b;mid[2]=c;
18     sort(mid,mid+3,cmp);
19     return mid[1];
20 }
21 int main()
22 {
23     int n,a[105],b[105],sum;
24     while(scanf("%d",&n)!=EOF)
25     {
26         sum=0;
27         for(int i=0;i<n;i++)
28         {
29             scanf("%d",&a[i]);
30             b[i]=a[i];
31         }
32         for(int i=1;i<n-1;i++)
33             b[i]=mid(b[i-1],b[i+1],a[i]);
34         for(int i=0;i<n;i++)
35             sum+=abs(a[i]-b[i]);
36         for(int i=1;i<n;i++)
37             sum+=abs(b[i]-b[i-1]);
38         printf("%d\n",sum);
39     }
40     return 0;
41 }

3.poj 1328

 题意: 给出在x轴上方的n个点,要在x轴上找最少的点以此为圆心,r为半径去覆盖那n个点。(经典贪心题目)
     要学会转化问题,根据这n个点计算出覆盖该点圆心的区间,然后问题就转化为给你n个区间求得独立区间(即互不相交)的个数。
     要使得点最少,就应该设置在区间右端点,若当前点的横坐标小于下一区间的左端点横坐标则计数加1,若当前点的横坐标大于下一区间
     右端点横坐标则更新当前点的横坐标。

View Code
 1 #include<iostream>
 2 #include<cstdio>
 3 #include<cstring>
 4 #include<cmath>
 5 #include<cstdlib>
 6 
 7 using namespace std;
 8 const int MAX=1005;
 9 
10 struct point
11 {
12     double r,l;
13 }p[MAX];
14 
15 int cmp(const void *a,const void *b)
16 {
17     point aa=*(point *)a;
18     point bb=*(point *)b;
19     if(aa.l>=bb.l)
20         return 1;
21     return -1;
22 }
23 
24 int main()
25 {
26     int n,sum,flag,k=1;
27     double ans,x,y,r;
28     while(scanf("%d%lf",&n,&r)!=EOF)
29     {
30         sum=1;
31         flag=1;
32         if(n==0&&r==0)
33             break;
34         for(int i=0;i<n;i++)
35         {
36             scanf("%lf%lf",&x,&y);
37             if(r>=y&&flag)
38             {
39                 p[i].l=x-sqrt(double(r*r-y*y));
40                 p[i].r=x+sqrt(double(r*r-y*y));
41             }
42             else
43                 flag=0;
44         }
45         printf("Case %d: ",k++);
46         if(!flag)
47             printf("-1\n");
48         else
49         {
50             qsort(p,n,sizeof(p[0]),cmp);
51             ans=p[0].r;
52             for(int i=1;i<n;i++)
53             {
54                 if(ans<p[i].l)
55                 {
56                     sum++;
57                     ans=p[i].r;
58                 }
59                 else
60                     if(ans>p[i].r)
61                         ans=p[i].r;
62             }
63              printf("%d\n",sum);
64         }
65 
66     }
67     return 0;
68 }

4.poj 1042

  待续...

posted @ 2012-08-04 11:15  hankers  阅读(278)  评论(0编辑  收藏  举报