ACM第三次比赛题目及标准程序(贪心)

来源:互联网 发布:ae 2017 cc mac破解版 编辑:程序博客网 时间:2024/05/16 12:00

欢迎访问XYNU


问题A: 灯光控制

时间限制: 1 Sec  内存限制: 128 MB

题目描述

灯光师小明控制着各种晚会的各种大小灯,每次晚会小明都会对灯进行很多次操作。对每盏灯只能进行两种操作,开和关。现在小明希望自己随时都知道还有多少盏灯亮着。你需要编写一个程序当小明问你时你能快速的说出还有多少盏灯亮着。 注意晚会开始时所有的灯都是灭的。

输入

只有一组数据.第一行输入两个正整数N,T(0<N<=100000,0<T<=1000000)N表示有N盏灯,T表示有T条指令。随后T行每行有一条指令,这条指令包含一个字符串,当字符串为CHANGE,它后面还有一个整数m,表示对第m盏灯进行一次操作(操作表示如果第m盏灯灯是开着时就关闭,如果灯是关着时就打开)。当字符串为QUERY,表示小明想查询现在还有多少盏灯亮着。

输出

每次查询指令输出占一行,输出当前亮着灯的个数

样例输入

10 8
CHANGE 1
QUERY
CHANGE 2
QUERY
CHANGE 1
CHANGE 9
CHANGE 7
QUERY

样例输出

1
2
3

提示

显然灯的序号是从1开始的。

[html] view plain copy
  1. #include<stdio.h>  
  2. int main()  
  3. {  
  4.     int n, t, m, count = 0, a[100005] = {0};  
  5.     char s[20];  
  6.     scanf("%d%d", &n, &t);  
  7.     for(int i = 0; i < t; i++) {  
  8.         scanf("%s", s);  
  9.         if(s[0] == 'C')  
  10.         {  
  11.             scanf("%d", &m);  
  12.             a[m] = !a[m];  
  13.             if(a[m]) count++;  
  14.             else count--;  
  15.         }  
  16.         if(s[0] == 'Q')  
  17.             printf("%d\n", count);  
  18.     }  
  19. }  

问题B: 彩灯统计

时间限制: 1 Sec  内存限制: 128 MB

题目描述

儿童乐园有各种颜色的彩灯,小明想要知道哪种颜色的灯数量最多。但是由于数据过于庞大,小明也束手无策,所以他想请聪明如你的ACMer来帮忙。

输入

第一行输入彩灯的数量N(1<= N <= 1000),接下来的N行输入N个字符串表示彩灯的颜色(字符串的长度不超过10,字符串全为小写字母,并且只有一组测试数据)。保证彩灯颜色不超过1000种。

输出

输出这些彩灯中最多的颜色的名字与数量,并用空格隔开(数据保证最多的颜色只有一个)。

样例输入

12
red
green
blue
white
red
green
blue
white
red
green
blue
red

样例输出

red 4
[html] view plain copy
  1. #include<stdio.h>  
  2. #include<string.h>  
  3. int main()  
  4. {  
  5.     int n;  
  6.     char a[1010][10];  
  7.     int b[1010]={0};  
  8.     char c[10];  
  9.     scanf("%d",&n);  
  10.     int m=1,i;  
  11.     int d=n;  
  12.     scanf("%s",a[0]);  
  13.     n--;  
  14.     b[0]++;  
  15.     while(n--)  
  16.     {  
  17.         scanf("%s",c);  
  18.         for(i=0;i<m;i++)  
  19.         {  
  20.             if(!strcmp(c,a[i]))  
  21.             {  
  22.                 b[i]++;  
  23.                 break;  
  24.             }  
  25.         }  
  26.         if(i==m)  
  27.         {  
  28.             strcpy(a[i],c);  
  29.             b[i]++;  
  30.             m++;  
  31.         }  
  32.     }  
  33.     int max=0;  
  34.     for(i=1;i<d;i++)  
  35.     {  
  36.         if(b[max]<b[i])  
  37.             max=i;  
  38.     }  
  39.     printf("%s %d\n",a[max],b[max]);  
  40.     return 0;  
  41. }  

问题C: 背包问题

时间限制: 3 Sec  内存限制: 128 MB

题目描述

现在有很多物品(它们是可以分割的),我们知道它们每个物品的总价值v和重量w(1<=v,w<=100;如果给你一个背包它能容纳的重量为m(10<=m<=100),你所要做的就是把物品装到背包里,使背包里的物品的价值总和最大。

输入

第一行输入一个正整数n(1<=n<=5),表示有n组测试数据;
随后有n组测试数据,每组测试数据的第一行有两个正整数s,m(1<=s<=10);s表示有s个物品。接下来的s行每行有两个正整数v,w。

输出

输出每组测试数据中背包内的物品的价值和,每次输出占一行。

样例输入

1
3 15
50 10
16 82
7 9

样例输出

65
[cpp] view plain copy
  1. #include<stdio.h>  
  2. #include<algorithm>  
  3. using namespace  std;   
  4. struct goods{  
  5.     double V;  
  6.     double W;   
  7. }good[15];  
  8.   
  9. int cmp(goods a,goods b)  
  10. {  
  11.     return a.V/a.W  > b.V/b.W;   
  12. }   
  13. int main()  
  14. {  
  15.     int n;  
  16.     scanf("%d",&n);  
  17.     while(n--)  
  18.     {  
  19.         double m;  
  20.         int s;  
  21.         scanf("%d%lf",&s,&m);  
  22.         for(int i = 0; i < s; i++)   
  23.         {  
  24.             scanf("%lf%lf",&good[i].V,&good[i].W);  
  25.         }  
  26.         sort(good,good+s,cmp);  
  27.         double count = 0.0;  
  28.         for(int i = 0; i < s; i++)  
  29.         {  
  30.             if(m > good[i].W)  
  31.             {  
  32.                 m -= good[i].W;  
  33.                 count += good[i].V;  
  34.                 //printf("%lf\n",count);  
  35.                   
  36.             }else{  
  37.                 count += m*good[i].V/good[i].W;   
  38.                 //printf("%lf\n",count);  
  39.                 break;  
  40.             }  
  41.         }  
  42.         printf("%.0lf\n",count);  
  43.     }  
  44.     return 0;  
  45.  }   

问题D:买饼干

时间限制: 1 Sec  内存限制: 128 MB

题目描述

小明同学决定去鼎盛超市买点零食囤着慢慢吃。现在假设小明带着一定数量的现金要去超市采购饼干(散装)。如果超市有m种饼干,各种饼干的单价和重量已知,请问,为了满足更多饼干的需求(因为各种饼干味道差不多,当然是买的越多越好啊),最多能购买多少重量的饼干呢?

输入

输入数据首先包含一个正整数C,表示有C组测试用例,每组测试用例的第一行是两个整数n和m(0<n<=1000,0<m<=1000),分别表示现金的金额和饼干的种类,然后是m行数据,每行包含2个整数p和h(1<=p<=25,1<=h<=100),分别表示单价和对应饼干的重量。

输出

对于每组测试数据,请输出能够购买饼干的最多重量.(你可以假设现金买不光超市所有的饼干)。
每个实例的输出占一行,保留2位小数。

样例输入

1
7 2
3 3
4 4

样例输出

2.33

[cpp] view plain copy
  1. #include<stdio.h>  
  2. #include<algorithm>  
  3. using namespace std;  
  4. struct cookies{  
  5.     double p;  //单价   
  6.     double  h;  //重量   
  7. }cook[1005];  
  8. int cmp(cookies a,cookies b)  
  9. {  
  10.     return a.p < b.p;  
  11. }  
  12. int main()  
  13. {  
  14.     int C;  
  15.     scanf("%d",&C);  
  16.     while(C--)  
  17.     {  
  18.         double n;  
  19.         int m;  
  20.         scanf("%lf%d",&n,&m);  
  21.         for(int i =  0; i < m; i++)  
  22.         {  
  23.             scanf("%lf%lf",&cook[i].p,&cook[i].h);  
  24.         }  
  25.         sort(cook,cook+m,cmp);  
  26.         double count=0.0;  
  27.         for(int i = 0; i < m; i++)  
  28.         {  
  29.             if(n > cook[i].h * cook[i].p)  
  30.             {  
  31.                 n = n - cook[i].h * cook[i].p;  
  32.                 count += cook[i].h;  
  33.             }else{  
  34.                 count += n / cook[i].p;  
  35.                 break;  
  36.             }  
  37.         }  
  38.         printf("%.2lf\n",count);  
  39.     }  
  40. }  

问题E:魔法扫帚

时间限制: 1 Sec  内存限制: 128 MB

题目描述

魔法师工会为了让每一位魔法师学会飞行,决定从邓布利多校长那里买一批扫帚。我们假设一个魔法师有一个等级的数字来表示他的飞行技术。只有有较高水平的魔法师可以教水平较低的人,也就是说,前者的级别大于后者。一个魔法师最多只能有一个老师,当然,没有老师也是合法的。同样的,一个魔法师最多只能有一个学生,而没有学生也是可能的。老师可以教他的学生用同样的扫帚。当然,所有的魔法师在学会飞行前都必须在扫帚柄上练习。魔法扫帚很贵!那么,你能帮助魔法师公会计算最少需要多少把扫帚吗?

输入

输入文件包含多个测试用例。
在一个测试用例中,第一行包含一个正号N表示魔法师的数量(0≤N≤3000)
下面N行:每行只有一个非负整数,表示每个士兵的等级数。等级范围为0~30;

输出

对于每一个测试样例,输出需要扫帚数量的最小值。

样例输入

4
10
20
30
4
5
2
3
4
3
4

样例输出

1
2
[cpp] view plain copy
  1. #include<stdio.h>  
  2. int main()  
  3. {  
  4.     int  N;  
  5.     while(scanf("%d",&N)!=EOF)  
  6.     {  
  7.         int m,b[3005]={0},mark=0;  
  8.         for(int i = 0; i < N; i++)  
  9.         {  
  10.             scanf("%d",&m);  
  11.             b[m]++;  
  12.             if(b[m] > mark)  
  13.             {  
  14.                 mark = b[m];  
  15.             }   
  16.         }  
  17.         printf("%d\n",mark);  
  18.     }  
  19.     return 0;  
  20. }  

问题F:火柴字

时间限制: 1 Sec  内存限制: 128 MB

题目描述

小明得到了一盒火柴,他可以用这些火柴拼成各种数字。假设现有V根火柴,根据拼法的不同,拼成数字i 需要ai根火柴。

请你帮助他拼成最大的数字。

输入

有多个测试用例。
每一种情况下,第一行都包含一个非负整数V(0 ≤V ≤106)。
第二行包含九个正整数a1,a2,……,a9(1≤ai≤105)。

输出

打印出小明可以拼成的最大数字。如果他连拼成一个数字的火柴数量都不够,输出-1。

样例输入

55 4 3 2 1 2 3 4 529 11 1 12 5 8 9 10 6

样例输出

5555533
[cpp] view plain copy
  1. #include <stdio.h>  
  2.   
  3. int main()  
  4. {  
  5.     int v,i;int a[11];  
  6.     while(scanf("%d",&v)!=EOF)  
  7.     {  
  8.         int min,mark,count,M;  
  9.         scanf("%d",&a[1]);  
  10.         mark=1;  
  11.         min=a[1];  
  12.         for(i=2;i<=9;i++)  
  13.         {  
  14.             scanf("%d",&a[i]);  
  15.             if(a[i]<=min)  
  16.                 min=a[i],mark=i;  
  17.         }  
  18.         if(v<min)   
  19.         {  
  20.             printf("-1\n");  
  21.             continue;  
  22.         }  
  23.         count=v/min;  
  24.         M=v%min;  
  25.         while(M>0)  
  26.         {  
  27.             for(i=9;i>mark;i--)  
  28.                 if(a[i]-min<=M)  
  29.                 {  
  30.                     printf("%d",i);  
  31.                     count--;  
  32.                     M-=a[i]-min;  
  33.                     break;  
  34.                 }  
  35.             if(i==mark) break;  
  36.         }  
  37.         for(i=1;i<=count;i++)  
  38.             printf("%d",mark);  
  39.         printf("\n");     
  40.     }  
  41.     return 0;  
  42. }  


问题G: 火力覆盖

时间限制: 1 Sec  内存限制: 128 MB

题目描述

朱日和基地某次演习中,蓝军某火炮部队奉命对某长方形目标区域进行饱和打击。目标区域横向长w,纵向长h,军用卫星在它的横向中心线上不同位置处标记有n(n<=10000)个目标打击点,每个打击点i有对应不同型号的火炮负责打击,打击效果是让以打击点为中心半径为Ri的圆被火力覆盖。请选择尽量少的目标打击点,使整块目标区域被火力覆盖。

输入

第一行输入一个正整数N表示共有n次测试数据。
每一组测试数据的第一行有三个整数n,w,h,n表示共有n个目标打击点,w表示目标区域的横向长度,h表示目标区域的纵向长度。
随后的n行,都有两个整数xi和ri,xi表示第i个目标打击点的的横坐标(最左边为0),ri表示该目标打击点能火力覆盖的圆的半径

输出

每组测试数据输出一个正整数,表示共需要多少个目标打击点,每个输出单独占一行。
如果不存在一种能够把整个目标区域火力覆盖的方案,请输出0。

样例输入

22 8 61 14 52 10 64 56 5

样例输出

12
[cpp] view plain copy
  1. #include <stdio.h>      
  2. #include <math.h>      
  3. #include <algorithm>      
  4. using namespace std;     
  5. struct node{      
  6.     double le, ri;      
  7. }s[1005];      
  8. int cmp(node a, node b)      
  9. {      
  10.     return a.le < b.le;      
  11. }      
  12. int main()      
  13. {      
  14.     int n, t;      
  15.     double w, h;      
  16.     scanf("%d", &t);      
  17.     while(t --){      
  18.         scanf("%d%lf%lf", &n, &w, &h);      
  19.         h /= 2;      
  20.         int i, j;      
  21.         double temp, r;      
  22.         for(i = 0, j = 0; i < n; i ++){      
  23.             scanf("%lf%lf", &temp, &r);      
  24.             if(r <= h) continue;     
  25.             else{      
  26.                 double temp1 = sqrt(r*r-h*h);      
  27.                 s[j].le = temp -temp1;   
  28.                 s[j++].ri = temp+temp1;     
  29.             }      
  30.         }      
  31.         sort(s, s+j, cmp);    
  32.         if(s[0].le > 0) {printf("0\n"); continue;}       
  33.         double end = 0;      
  34.         i = 0;      
  35.         int cou = 0;      
  36.         while(end <= w&&i < j&&cou <= n){  
  37.             temp = end;      
  38.             while(s[i].le <= end&&i <j ){      
  39.                 if(s[i].ri > temp) temp = s[i].ri;      
  40.                 i++;      
  41.             }      
  42.             end = temp+0.000001;//每次都只加上0.00001,俩区间有断点,就能区分      
  43.             ++cou;      
  44.         }      
  45.         if(end < w||cou > n){     
  46.             printf("0\n");      
  47.         }      
  48.         else{       
  49.             printf("%d\n", cou);      
  50.         }      
  51.     }      
  52.     return 0;      
  53. }       

问题H: 搬木头的熊二

时间限制: 1 Sec  内存限制: 128 MB

题目描述

东北原始森林经历了风暴袭击,光头强的房子被摧毁了。正好森林有被风暴摧毁而散落的木头,熊大和熊二决定帮可怜的光头强修一座新房子。熊大负责把散落的木头收集成堆,熊二负责搬木头。熊二决定把所有的木头合成一堆。 因为熊二比较懒,为了省力气,熊二开始想点子了:


每一次合并,熊二可以把两堆木头合并到一起,消耗的体力等于两堆木头的重量之和。可以看出,所有的木头经过n-1次合并之后,就只剩下一堆了。熊二在合并木头时总共消耗的体力等于每次合并所耗体力之和。 
因为还要花大力气把这些木头搬走,所以熊二在合并木头时要尽可能地节省体力。假定每根木头重量都为1,并且已知木头的堆数和每堆木头的数目,你的任务是设计出合并的次序方案,使熊二耗费的体力最少,并输出这个最小的体力耗费值。 
例如有3堆木头,数目依次为1,2,9。可以先将1、2堆合并,新堆数目为3,耗费体力为3。接着,将新堆与原先的第三堆合并,又得到新的堆,数目为12,耗费体力为12。所以熊二总共耗费体力=3+12=15。可以证明15为最小的体力耗费值。

输入

第一行输入整数N(0<N<=10)表示测试数据组数。接下来每组测试数据输入包括两行,第一行是一个整数n(1<=n<=12000),表示木头的堆数。第二行包含n个整数,用空格分隔,第i个整数ai(1<=ai<=20000)是第i堆木头的数目。

输出

每组测试数据输出包括一行,这一行只包含一个整数,也就是最小的体力耗费值。

样例输入

3
1 2 9

样例输出

15
[html] view plain copy
  1. #include<stdio.h>  
  2. #include<algorithm>  
  3. using namespace std;  
  4. int main()  
  5. {  
  6.     int  N;  
  7.     scanf("%d",&N);  
  8.     while(N--)  
  9.     {  
  10.         int n;  
  11.         long long a[12005],b = 0;  
  12.         scanf("%d\n",&n);  
  13.         for(int i = 0; i < n; i++)  
  14.         {  
  15.             scanf("%lld",&a[i]);  
  16.         }  
  17.         sort(a,a+n);  
  18.            
  19.         for(int i = 1; i < n; i++)  
  20.         {  
  21.             sort(a,a+n);  
  22.             a[i] = a[i]+a[i-1];  
  23.             b += a[i] ;  
  24.            
  25.         }  
  26.         printf("%lld\n",b);   
  27.            
  28.     }  
  29. }  

原创粉丝点击