高级算法--贪心

下面是对信息学奥赛一本通网站评测上的AC代码的总结

·例一:

题目描述:

  设有n个活动的集合E={1,2,…,n},其中每个活动都要求使用同一资源,如演讲会场等,而在同一时间内只有一个活动能使用这一资源。每个活动i都有一个要求使用该资源的起始时间si和一个结束时间fi,且si <fi。如果选择了活动i,则它在半开时间区间[si, fi)内占用资源。若区间[si, fi)与区间[sj, fj)不相交,则称活动i与活动j是相容的。也就是说,当si≥fj或sj≥fi时,活动i与活动j相容。选择出由相互兼容的活动组成的最大集合。

代码实现:

 

 1 #include<algorithm>
 2 #include<iostream>
 3 #include<cstdio>
 4 
 5 using namespace std;
 6 
 7 struct node
 8 {
 9     int st;
10     int ed;
11 }a[1005];
12 
13 bool cmp(node x,node y)
14 {
15     return x.ed<y.ed;
16 }
17 
18 int main()
19 {
20     int n;
21     scanf("%d",&n);
22     for(int i=1;i<=n;++i)    scanf("%d%d",&a[i].st,&a[i].ed);
23     sort(a+1,a+n+1,cmp);
24     int t=a[1].ed;
25     int ans=1;
26     for(int i=2;i<=n;++i)
27     {
28         if(a[i].st>=t)
29         {
30             ans++;
31             t=a[i].ed;
32         }
33     }
34     printf("%d",ans);
35     return 0;
36 }

 

·例二:

题目描述:

  现在我们国家开展新农村建设,农村的住房建设纳入了统一规划,统一建设,政府要求每一住户门口种些树。门口路边的地区被分割成块,并被编号成1..N。每个部分为一个单位尺寸大小并最多可种一棵树。每个居民房子门前被指定了三个号码B,E,T。这三个数表示该居民想在B和E之间最少种T棵树。当然,B≤E,居民必须记住在指定区不能种多于区域地块数的树,所以T≤E-B+l。居民们想种树的各自区域可以交叉。你的任务是求出能满足所有要求的最少的树的数量,尽量较少政府的支出。

代码实现:

 1 #include<iostream>
 2 #include<cstdio>
 3 #include<algorithm>
 4 
 5 using namespace std;
 6 
 7 struct line{int s,e,v;}a[5005];
 8 
 9 int n,m;
10 
11 bool used[30005]={0};
12 
13 bool cmp(const line &x,const line &y){return x.e<y.e;}
14 
15 void init()
16 {
17     int i;
18     scanf("%d%d",&n,&m);
19     for(i=1;i<=m;++i) scanf("%d%d%d",&a[i].s,&a[i].e,&a[i].v);
20     sort(a+1,a+m+1,cmp);
21 }
22 
23 void solve()
24 {
25     int i,j,k,ans=0;
26     for(int i=1;i<=m;++i)
27     {
28         k=0;
29         for(j=a[i].s;j<=a[i].e;++j)    if(used[j]) ++k;
30         if(k>=a[i].v) continue;
31         for(j=a[i].e;j>=a[i].s;--j)
32             if(!used[j])
33             {
34                 used[j]=1;
35                 k++;
36                 ans++;
37                 if(a[i].v==k) break;
38             }
39     }
40     printf("%d",ans);
41 }
42 
43 int main()
44 {
45     init();
46     solve();
47     return 0;
48 }

·例三:

题目描述:

长L米,宽W米的草坪里装有n个浇灌喷头。每个喷头都装在草坪中心线上(离两边各W/2米)。我们知道每个喷头的位置(离草坪中心线左端的距离),以及它能覆盖到的浇灌范围。

请问:如果要同时浇灌整块草坪,最少需要打开多少个喷头?

代码实现:

 1 #include <cstdio>
 2 #include <cstring>
 3 #include <cmath>
 4 #include <algorithm>
 5 #define N 300005
 6  
 7 using namespace std;
 8  
 9 const double Eps = 1e-5 ;
10  
11 inline int wread(){
12     char c=getchar ();int flag=1,wans=0;
13     while (c<'0'||c>'9'){if (c=='-') flag=-1;c=getchar ();}
14     while (c>='0'&&c<='9'){wans=wans*10+c-'0';c=getchar ();}
15     return wans*=flag;
16 }
17  
18 int T;
19 int n,L,W;
20 struct node {double lx,rx;int pos,r;}a[N];
21 bool e666 (node x,node y){return x.lx<y.lx;}
22  
23 int main (){
24     T=wread();
25     while (T--){
26         memset (a,0,sizeof a);
27         n=wread();L=wread();W=wread();
28         for (int i=1;i<=n;++i){
29             a[i].pos=wread(),a[i].r=wread();
30             if (a[i].r*a[i].r-(W*1.0/2.0)*(W*1.0/2.0)<0)    a[i].pos=-1,a[i].lx=-1,a[i].rx=-1;
31             //对于不能覆盖完草坪上端的一个圆(例如样例1中的那个夹在草坪中间的圆) 肯定是不会选它的 
32             else {
33                 a[i].lx=max (0.000000,(double)a[i].pos-sqrt((double)a[i].r*(double)a[i].r-(W*1.0/2.0)*(W*1.0/2.0)));
34                 a[i].rx=a[i].pos+sqrt((double)a[i].r*(double)a[i].r-(W*1.0/2.0)*(W*1.0/2.0));                    
35             }
36         }
37  
38         sort (a+1,a+n+1,e666);    
39         
40         int nx=1; 
41         double s=0;//起点 
42         bool F=true;//判断是否能覆盖完整个区间 
43         int ans=0;//记录 
44         
45         while (nx<=n){
46             ans++;
47             double re=s;
48             while (a[nx].lx<=re && nx<=n){//模板 
49                 if (a[nx].rx>=re)    s=max(s,a[nx].rx);
50                 nx++;
51             }
52             if (s>=L)    {break;}
53             if (re==s)    {F=false;break;}//未更新,请画图____即当前区间与下个区间之间 一定有一段距离,不符合全部覆盖的要求,退出 
54         }
55         if (!F)    puts("0");
56         else    printf("%d\n",ans);
57     }
58     return 0;
59 }

·例四:

题目描述:

  某工厂收到了n个产品的订单,这n个产品分别在 A、B 两个车间加工,并且必须先在 A 车间加工后才可以到 B 车间加工。

某个产品i在 A,B 两车间加工的时间分别为Ai,Bi。怎样安排这个产品的加工顺序,才能使总的加工时间最短。

这里所说的加工时间是指:从开始加工第一个产品到最后所有的产品都已在 A,B 两车间加工完毕的时间。

代码实现:

 1 #include<cstdio>
 2 #include<iostream>
 3 
 4 using namespace std;
 5 
 6 int ans[1005],n,k,i,j,t,a[1005];
 7 int b[1005],m[1005],s[1005];
 8 
 9 void read()
10 {
11     int i;
12     scanf("%d",&n);
13     for(i=1;i<=n;++i) scanf("%d",&a[i]);
14     for(i=1;i<=n;++i) scanf("%d",&b[i]);
15 }
16 
17 void solve()
18 {
19     for(i=1;i<=n;++i){m[i]=min(a[i],b[i]);s[i]=i;}
20     for(i=1;i<=n-1;++i)
21         for(j=i+1;j<=n;++j)
22             if(m[i]>m[j]){swap(m[i],m[j]);swap(s[i],s[j]);}
23     k=0;t=n+1;
24     for(i=1;i<=n;++i)
25         if(m[i]==a[s[i]]){k++;ans[k]=s[i];}
26         else{t--;ans[t]=s[i];}
27     k=0;t=0;
28     for(i=1;i<=n;++i)
29     {
30         k+=a[ans[i]];
31         if(t<k) t=k;
32         t+=b[ans[i]];
33     }
34     printf("%d\n",t);
35     for(i=1;i<=n;++i) printf("%d ",ans[i]);
36     printf("\n");
37 }
38 
39 int main()
40 {
41     read();
42     solve();
43     return 0;
44 }

 

posted @ 2019-06-08 20:42  蒟蒻hqk  阅读(263)  评论(0编辑  收藏  举报