noip2007普及组T1--T4题解

来源:互联网 发布:js如何控制光标大小 编辑:程序博客网 时间:2024/05/19 06:34

T1:奖学金

Description

  某小学最近得到了一笔赞助,打算拿出其中一部分为学习成绩优秀的前5名学生发奖学金。期末,每个学生都有3门课的成绩:语文、数学、英语。先按总分从高到低排序,如果两个同学总分相同,再按语文成绩从高到低排序,如果两个同学总分和语文成绩都相同,那么规定学号小的同学排在前面,这样,每个学生的排序是唯一确定的。

    任务:先根据输入的3门课的成绩计算总分,然后按上述规则排序,最后按排名顺序输出前5名学生的学号和总分。注意,在前5名同学中,每个人的奖学金都不相同,因此,你必须严格按上述规则排序。例如,在某个正确答案中,如果前两行的输出数据(每行输出两个数:学号、总分)是:

    7  279

    5  279

    这两行数据的含义是:总分最高的两个同学的学号依次是7号、5号。这两名同学的总分都是279(总分等于输入的语文、数学、英语三科成绩之和),但学号为7的学生语文成绩更高一些。如果你的前两名的输出数据是:

    5  279

    7  279

    则按输出错误处理,不能得分。 

Input

  输入包含n+1行:

    第l行为一个正整数n,表示该校参加评选的学生人数。

    第2到年n+l行,每行有3个用空格隔开的数字,每个数字都在0到100之间。第j行的3个数字依次表示学号为j-1的学生的语文、数学、英语的成绩。每个学生的学号按照输入顺序编号为1~n(恰好是输入数据的行号减1)。

    所给的数据都是正确的,不必检验。 

Output

  输出共有5行,每行是两个用空格隔开的正整数,依次表示前5名学生的学号和总分。 

Sample Input

Sample 1:
6
90 67 80
87 66 91
78 89 91
88 99 77
67 89 64
78 89 98
Sample 2:
8
80 89 89
88 98 78
90 67 80
87 66 91
78 89 91
88 99 77
67 89 64
78 89 98

Sample Output

Sample 1:
6 265
4 264
3 258
2 244
1 237
Sample 2:
8 265
2 264
6 264
1 258
5 258

HINT

50%的数据满足:各学生的总成绩各不相同  100%的数据满足:6< =n< =300 

此题为水题,T1不想解释

#include<stdio.h>int main(){    int i,j,k,n,yu[301],shu[301],ying[301],zong[301],id[301],t;    scanf("%d",&n);    for(i=1;i<=n;i++)    {        scanf("%d%d%d",&yu[i],&shu[i],&ying[i]);        zong[i]=yu[i]+shu[i]+ying[i];        id[i]=i;    }    for(i=1;i<=n;i++)    {        for(j=2;j<=n;j++)        {           if(zong[i]<zong[j]&&i<j)           {           t=yu[j];           yu[j]=yu[i];           yu[i]=t;               t=zong[j];           zong[j]=zong[i];           zong[i]=t;           t=id[j];           id[j]=id[i];           id[i]=t;           }           else if(zong[j]==zong[i]&&i<j)           {               if(yu[i]<yu[j])               {                   t=yu[j];                   yu[j]=yu[i];                   yu[i]=t;                  t=id[j];                  id[j]=id[i];                  id[i]=t;               }               else if(yu[i]==yu[j]&&i!=j)               {                   if(id[i]>id[j])                   {                    t=id[j];                  id[j]=id[i];                  id[i]=t;                   }               }           }        }    }    for(i=1;i<6;i++)    {        printf("%d %d\n",id[i],zong[i]);    }}
T2:纪念品分组

Description

元旦快到了,校学生会让乐乐负责新年晚会的纪念品发放工作。

为使得参加晚会的同学所获得的纪念品价值相对均衡,他要把购来的纪念品根据价格进行分组,但每组最多只能包括两件纪念品,  并且每组纪念品的价格之和不能超过一个给定的整数。

为了保证在尽量短的时间内发完所有纪念品,乐乐希望分组的数目最少。 

你的任务是写一个程序,找出所有分组方案中分组数最少的一种,输出最少的分组数目。

【限制】

  50%的数据满足:  1  < =n  < =  15

  100%的数据满足:  1  < =  n  < =  30000,  80  < =  W  < =  200   

Input

第1行包括一个整数w,为每组纪念品价格之和的上限=

第2行为一个整数n,表示购来的纪念品的总件数G

第3-n+2行每行包含一个正整数Pi  (5  < =  Pi  < =  w3) w表示所对应纪念品的价格。 

Output

仅1行,包含一个整数,  ep最少的分组数目合 

Sample Input

100
9
90
20
20
30
50
60
70
80
90

Sample Output

6

先排序,前后左端点与右端点一起找尽量两两一组。

#include<algorithm>using namespace std;#include<stdio.h>int a[30001];int main(){int x,n,ans=0,i;scanf("%d%d",&x,&n);for(i=1;i<=n;i++)   scanf("%d",&a[i]);    sort(a+1,a+n+1);    int q=1,r=n;    while(q<=r)    {    if(a[q]+a[r]<=x){q++;r--;}    else r--;    ans++;    }    if(q==r)ans++;    printf("%d",ans);}
T3:守望者的逃离

Description

        恶魔猎手尤迪安野心勃勃,他背叛了暗夜精灵,率领深藏在海底的娜迦族企图叛变。守望者 在与尤迪安的交锋中遭遇了围杀,被困在一个荒芜的大岛上。为了杀死守望者,尤迪安开始对这 个荒岛施咒,这座岛很快就会沉下去。到那时,岛上的所有人都会遇难。守望者的跑步速度为 17m/s,以这样的速度是无法逃离荒岛的。庆幸的是守望者拥有闪烁法术,可在1s内移动60m,不 过每次使用闪烁法术都会消耗魔法值10点。守望者的魔法值恢复的速度为4点/s,只有处在原地 休息状态时才能恢复。

        现在已知守望者的魔法初值M,他所在的初始位置与岛的出口之间的距离S,岛沉没的时间T。 你的任务写写一个程序帮助守望者计算如何在最短的时间内逃离荒岛,若不能逃出,则输出守望 者在剩下的时间能走的最远距离。注意:守望者跑步、闪烁或休息活动均以秒(s)为单位,且每 次活动的持续时间为整数秒。距离的单位为米(m)。

Input

在输入仅一行,包括空格隔开的三个非负整数M,S,T。

Output

在输出包括两行:

  第1行为字符串“Yes”或“No”(区分大小写),即守望者是否能逃离荒岛。

  第2行包含一个整数。第一行为“Yes”(区分大小写)时表示守望者逃离荒岛的最短时间; 第一行为“No”(区分大小写)时表示守望者能走的最远距离。

Sample Input

【输入样例1】
39 200 4
【输入样例2】
36 255 10

Sample Output

【输出样例1】
No
197
【输出样例2】
Yes
6

HINT

30%的数据满足:1< =T< =10,1< =S< =100

50%的数据满足:1< =T< =1000,1< =S< =10000 

100%的数据满足:1< =T< =300000,0< =M< =1000,1< =S< =108

贪心,也可以DP

#include<stdio.h>int main() {int m,s,t; int i,x,y;   scanf("%d%d%d",&m,&s,&t);   x=y=0;    for(i=1;i<=t;i++) { if(m>=10) {  x+=60;   m-=10;           } else   m+=4;         if(x>y+17)  y=x;         else  y+=17;         if(y>=s)  break;     }     if(i>t)  printf("No\n%d",y);     else  printf("Yes\n%d",i);}

Description

        给定A,B,C三根足够长的细柱,在A柱上放有2n个中间有孔的圆盘,共有n个不同的尺寸,每个尺寸都有两个相同的圆盘,注意这两个圆盘是不加区分的。现要将这些圆盘移到C柱上,在移动过程中可放在B柱上暂存。要求:  

 

 (1)每次只能移动一个圆盘;    (2)  A、B、C三根细柱上的圆盘都要保持上小下大的顺序;    任务:设An为2n个圆盘完成上述任务所需的最少移动次数,对于输入的n,输出An。

Input

输入为一个正整数n,表示在A柱上放有2n个圆盘。

Output

仅一行,包含一个正整数,为完成上述任务所需的最少移动次数An。

Sample Input

Sample 1:
1
Sample 2:
2

Sample Output

Sample 1:
2
Sample 2:
6

HINT

对于50%的数据,  1< =n< =25

对于100%  数据,  1< =n< =200   

这道题基本是T4最水的题了,答案是2的n+1次幂-2
#include<stdio.h>int f[201]={0,1};int main(){int n,i,j,x;scanf("%d",&n);for(i=1;i<=n+1;i++){for(j=1;j<=n+1;j++){f[j]=f[j]*2;}for(j=1;j<=n+1;j++){if(f[j]>=10){f[j+1]+=f[j]/10;f[j]=f[j]%10;}}}f[1]=f[1]-2;if(f[1]<0){f[2]-=1;f[1]+=10;}for(i=n+1;i>0;i--){if(f[i]!=0){x=i;break;}}for(i=x;i>0;i--)printf("%d",f[i]);}



原创粉丝点击