noip2005题解

T1谁拿了最多奖学金

描述

某校的惯例是在每学期的期末考试之后发放奖学金。发放的奖学金共有五种,获取的条件各自不同:

1) 院士奖学金,每人8000元,期末平均成绩高于80分(>80),并且在本学期内发表1篇或1篇以上论文的学生均可获得;

2) 五四奖学金,每人4000元,期末平均成绩高于85分(>85),并且班级评议成绩高于80分(>80)的学生均可获得;

3) 成绩优秀奖,每人2000元,期末平均成绩高于90分(>90)的学生均可获得;

4) 西部奖学金,每人1000元,期末平均成绩高于85分(>85)的西部省份学生均可获得;

5) 班级贡献奖,每人850元,班级评议成绩高于80分(>80)的学生干部均可获得;

只要符合条件就可以得奖,每项奖学金的获奖人数没有限制,每名学生也可以同时获得多项奖学金。例如姚林的期末平均成绩是87分,班级评议成绩82分,同时他还是一位学生干部,那么他可以同时获得五四奖学金和班级贡献奖,奖金总数是4850元。

现在给出若干学生的相关数据,请计算哪些同学获得的奖金总数最高(假设总有同学能满足获得奖学金的条件)。

格式

输入格式

输入的第一行是一个整数N(1 <= N <= 100),表示学生的总数。接下来的N行每行是一位学生的数据,从左向右依次是姓名,期末平均成绩,班级评议成绩,是否是学生干部,是否是西部省份学生,以及发表的论文数。姓名是由大小写英文字母组成的长度不超过20的字符串(不含空格);期末平均成绩和班级评议成绩都是0到100之间的整数(包括0和100);是否是学生干部和是否是西部省份学生分别用一个字符表示,Y表示是,N表示不是;发表的论文数是0到10的整数(包括0和10)。每两个相邻数据项之间用一个空格分隔。

输出格式

输出包括三行,第一行是获得最多奖金的学生的姓名,第二行是这名学生获得的奖金总数。如果有两位或两位以上的学生获得的奖金最多,输出他们之中在输入文件中出现最早的学生的姓名。第三行是这N个学生获得的奖学金的总数。

样例1

样例输入1[复制]

 
4
YaoLin 87 82 Y N 0
ChenRuiyi 88 78 N Y 1
LiXin 92 88 N N 0
ZhangQin 83 87 Y N 1

样例输出1[复制]

 
ChenRuiyi
9000
28700

限制

1s

 

模拟题,当时写的时候cmp函数没有写价值相等时按名称排序,w了一个点...

vijos1001

 1 #include<iostream>
 2 #include<string.h>
 3 #include<cstdlib>
 4 #include<stdio.h>
 5 #include<algorithm>
 6 using namespace std;
 7 struct object
 8 {
 9     int answer,cx;
10     char name[21];
11 }q[100001];
12 
13 int cmp(object a,object b)
14 {
15     if(a.answer!=b.answer)
16      return a.answer>b.answer;
17     else return a.cx<b.cx;
18 }
19 
20 int main()
21 {
22      int n,p1,p2,p3,answer;
23      int i1,i2;
24     answer=0;
25     cin>>n;
26     for(int i=0;i<n;i++)
27     {
28         cin>>q[i].name>>p1>>p2;
29         i1=getchar();
30         while(i1!='N'&&i1!='Y')
31          i1=getchar();
32         i2=getchar();
33         while(i2!='N'&&i2!='Y')
34          i2=getchar();
35         cin>>p3;
36         q[i].answer=0;
37         if(p1>80&&p3>=1)
38          q[i].answer+=8000;
39         if(p1>85&&p2>80)
40          q[i].answer+=4000;
41         if(p1>90)
42          q[i].answer+=2000;
43         if(p1>85&&i2=='Y')
44          q[i].answer+=1000;
45         if(p2>80&&i1=='Y')
46          q[i].answer+=850;
47         answer+=q[i].answer;
48         q[i].cx=i;
49     }
50     sort(q,q+n,cmp);
51     cout<<q[0].name<<endl;
52     cout<<q[0].answer<<endl;
53     cout<<answer;
54     return 0;
55 }

 

T2过河

描述

在河上有一座独木桥,一只青蛙想沿着独木桥从河的一侧跳到另一侧。在桥上有一些石子,青蛙很讨厌踩在这些石子上。由于桥的长度和青蛙一次跳过的距离都是正整数,我们可以把独木桥上青蛙可能到达的点看成数轴上的一串整点:0,1,……,L(其中L是桥的长度)。坐标为0的点表示桥的起点,坐标为L的点表示桥的终点。青蛙从桥的起点开始,不停的向终点方向跳跃。一次跳跃的距离是S到T之间的任意正整数(包括S,T)。当青蛙跳到或跳过坐标为L的点时,就算青蛙已经跳出了独木桥。

题目给出独木桥的长度L,青蛙跳跃的距离范围S,T,桥上石子的位置。你的任务是确定青蛙要想过河,最少需要踩到的石子数。

对于30%的数据,L <= 10000;
对于全部的数据,L <= 10^9。

格式

输入格式

输入的第一行有一个正整数L(1 <= L <= 10^9),表示独木桥的长度。第二行有三个正整数S,T,M,分别表示青蛙一次跳跃的最小距离,最大距离,及桥上石子的个数,其中1 <= S <= T <= 10,1 <= M <= 100。第三行有M个不同的正整数分别表示这M个石子在数轴上的位置(数据保证桥的起点和终点处没有石子)。所有相邻的整数之间用一个空格隔开。

输出格式

输出只包括一个整数,表示青蛙过河最少需要踩到的石子数。

样例1

样例输入1[复制]

 
10
2 3 5
2 3 5 6 7

样例输出1[复制]

 
2

限制

1s

 

dp,f[i]表示到达i点踩到的石子最小个数,这样做明显超时,所以考虑优化。发现在f[i]数组中有很长的连续部分,考虑f[i]的值重复的条件,可以得到如果某f[i]已经连续出现了T次,那么在遇到下一个石子之前它将一直重复,所以可以剪枝

当时的代码风格也是很迷醉...不会用sort的我+for里面变量名写的玄妙的我...

vijos1002

 1 #include<iostream>
 2 #include<cstdlib>
 3 #include<stdio.h>
 4 using namespace std;
 5 int f[10],stone[200],L,S,T,M,count=0,ans=999999999,now=0,num=0;
 6 
 7 int devide(int l, int r)
 8 {
 9     int x=stone[(l+r)/2],i=l-1,j=r+1;
10     while(1)
11     {
12         do{--j;}
13         while(stone[j]>x);
14 
15         do{++i;}
16         while(stone[i]<x);
17         
18         if(i<j)
19         {
20             int t=stone[i];
21             stone[i]=stone[j];
22             stone[j]=t;
23         }
24         else return j;
25     }
26 }
27 
28 void qsort(int l,int r)
29 {
30      int p;
31      if(l<r)
32      {
33          p=devide(l,r);
34          qsort(l,p);
35          qsort(p+1,r);
36      }
37 }
38 
39 int main()
40 {
41     cin>>L>>S>>T>>M;
42     for(int i=0;i<M;i++)
43      cin>>stone[i];
44     qsort(0,M-1);
45     f[0]=0;
46     for(int i=1;i<10;i++)f[i]=9999999999;
47     
48     if(S==T)
49     {
50         int nowans=0;
51         for(int i=0;i<M;i++)
52          if(stone[i]%S==0)nowans++;
53         cout<<nowans<<endl;
54         return 0;
55     }
56     for(int i=1;i<L+T;i++)
57     {
58         for(int j=S;j<=T;j++)
59          if(f[(i-j+T)%T]<f[i%T])f[i%T]=f[(i-j+T)%T];
60         if(stone[count]==i)
61         {
62             count++;
63             f[i%T]++;
64         }
65         if(now==f[i%T])
66          num++;
67         else
68         {
69             now=f[i%T];
70             num=0;
71         }
72         if(num==T)
73         {
74             if(count==M)
75             {
76                 cout<<f[i%T]<<endl;
77                 return 0;
78             }
79             else i=stone[count]-1;
80         }
81     }
82     for(int i=0;i<T;i++)
83      if(f[i]<ans)ans=f[i];
84     cout<<ans<<endl;
85     return 0;
86 }

 

 

T3等价表达式

描述

明明进了中学之后,学到了代数表达式。有一天,他碰到一个很麻烦的选择题。这个题目的题干中首先给出了一个代数表达式,然后列出了若干选项,每个选项也是一个代数表达式,题目的要求是判断选项中哪些代数表达式是和题干中的表达式等价的。

这个题目手算很麻烦,因为明明对计算机编程很感兴趣,所以他想是不是可以用计算机来解决这个问题。假设你是明明,能完成这个任务吗?

这个选择题中的每个表达式都满足下面的性质:

1. 表达式只可能包含一个变量‘a’。

2. 表达式中出现的数都是正整数,而且都小于10000。

3. 表达式中可以包括四种运算‘+’(加),‘-’(减),‘*’(乘),‘^’(乘幂),以及小括号‘(’,‘)’。小括号的优先级最高,其次是‘^’,然后是‘*’,最后是‘+’和‘-’。‘+’和‘-’的优先级是相同的。相同优先级的运算从左到右进行。(注意:运算符‘+’,‘-’,‘*’,‘^’以及小括号‘(’,‘)’都是英文字符)

4. 幂指数只可能是1到10之间的正整数(包括1和10)。

5. 表达式内部,头部或者尾部都可能有一些多余的空格。

下面是一些合理的表达式的例子:

((a^1) ^ 2)^3,a*a+a-a,((a+a)),9999+(a-a)*a,1 + (a -1)^3,1^10^9……

对于30%的数据,表达式中只可能出现两种运算符‘+’和‘-’;

对于其它的数据,四种运算符‘+’,‘-’,‘*’,‘^’在表达式中都可能出现。

对于全部的数据,表达式中都可能出现小括号‘(’和‘)’。

格式

输入格式

输入的第一行给出的是题干中的表达式。第二行是一个整数n(2 <= n <= 26),表示选项的个数。后面n行,每行包括一个选项中的表达式。这n个选项的标号分别是A,B,C,D……

输入中的表达式的长度都不超过50个字符,而且保证选项中总有表达式和题干中的表达式是等价的。

输出格式

输出包括一行,这一行包括一系列选项的标号,表示哪些选项是和题干中的表达式等价的。选项的标号按照字母顺序排列,而且之间没有空格。

样例1

样例输入1[复制]

 
( a + 1) ^2
3
(a-1)^2+4*a
a  + 1+ a
a^2 + 2 * a * 1 + 1^2 + 10 -10 +a -a

样例输出1[复制]

 
AC

限制

1s

 

题意几乎就是裸的..由于次数小于等于10,我们只需要枚10个值代入每个表达式算一算,十个值都相等就一定是等价表达式

但是代码能力拙计...也没有什么办法,这个题我的代码过了noip的数据但是没有过vijos的,而且长度和编程时间也是不尽人意...

注意:

1.由于有可能出现爆longlong,要取模(所以也最好多计算几组)

2.long long在外部函数的传入
3.顺序是从前往后(^和减法都需要,减法的优先级高于加法),所以按照我的栈的写法需要先出栈到另外一个栈再计算
4.计算数字的字符->int部分注意停止的条件
vijos1003
  1 #include<iostream>
  2 #include<stdio.h>
  3 #include<string.h>
  4 #include<cstdlib>
  5 #include<algorithm>
  6 #define M 100
  7 #define NUM 12
  8 #define mod 1000000007
  9 using namespace std;
 10 int n;
 11 long long num[20];
 12 char s[M];
 13 long long answer[20];
 14 int len;
 15 
 16 struct object
 17 {
 18     long long a;
 19     int type;
 20 };
 21 
 22 class Stack
 23 {
 24 private:
 25     int rear;
 26     object stack[M];
 27 public:
 28     Stack()
 29     {
 30         rear=-1;
 31     }
 32     void Setstack()
 33     {
 34         rear=-1;
 35     }
 36     object Destack()
 37     {
 38         object x=stack[rear];
 39         rear--;
 40         return x;
 41     }
 42     void Enstack(object x)
 43     {
 44         rear++;
 45         stack[rear]=x;
 46     }
 47     object Getrear()
 48     {
 49         return stack[rear];
 50     }
 51     int Getsize()
 52     {
 53         return rear+1;
 54     }
 55 }ms,cs;
 56 
 57 long long pow(int a,int b)
 58 {
 59     long long thi=1;
 60     for(int i=0;i<b;i++)
 61      thi*=a,thi=(thi%mod+mod)%mod;
 62     return thi;
 63 }
 64 
 65 long long cul()
 66 {
 67     cs.Setstack();
 68     object thi;
 69     while(ms.Getsize()&&!(ms.Getrear().a==-1&&ms.Getrear().type==1))
 70      cs.Enstack(ms.Destack());
 71     while(cs.Getsize())
 72     {
 73         thi=cs.Destack();
 74         if(thi.type==1&&thi.a==0)
 75         {
 76             thi.a=pow(ms.Destack().a,cs.Destack().a);
 77             thi.type=0;
 78             ms.Enstack(thi);
 79         }
 80         else ms.Enstack(thi);
 81     }
 82     while(ms.Getsize()&&!(ms.Getrear().a==-1&&ms.Getrear().type==1))
 83     {
 84         thi=ms.Destack();
 85         if(thi.type==1&&thi.a==1)
 86         {
 87             thi.a=(ms.Destack().a*cs.Destack().a%mod+mod)%mod;
 88             thi.type=0;
 89             cs.Enstack(thi);
 90         }
 91         else cs.Enstack(thi);
 92     }
 93     while(cs.Getsize())
 94     {
 95         thi=cs.Destack();
 96         if(thi.type==1&&thi.a==3)
 97         {
 98             thi.a=((ms.Destack().a-cs.Destack().a)%mod+mod)%mod;
 99             thi.type=0;
100             ms.Enstack(thi);
101         }
102         else ms.Enstack(thi);
103     }
104     while(cs.Getsize())
105      ms.Enstack(cs.Destack());
106     while(ms.Getsize()&&!(ms.Getrear().a==-1&&ms.Getrear().type==1))
107     {
108         thi=ms.Destack();
109         if(thi.type==1&&thi.a==2)
110         {
111             thi.a=((ms.Destack().a+cs.Destack().a)%mod+mod)%mod;
112             thi.type=0;
113             cs.Enstack(thi);
114         }
115         else cs.Enstack(thi);
116     }
117     if(ms.Getrear().a==-1)
118      ms.Destack();
119     thi=cs.Destack();
120     return thi.a;
121 }
122 
123 long long does(char *s,int x)
124 {
125     ms.Setstack();
126     for(int i=0;i<len;i++)
127     {
128         object thi;
129         if(s[i]>='0'&&s[i]<='9')
130         {
131             long long now=0;
132             while(s[i]>='0'&&s[i]<='9'&&i<len)
133             {
134                 now*=10;
135                 now+=s[i]-'0';
136                 i++;
137             }
138             i--;
139             thi.a=now;
140             thi.type=0;
141             ms.Enstack(thi);
142         }
143         else if(s[i]=='a')
144         {
145             thi.a=x;
146             thi.type=0;
147             ms.Enstack(thi);
148         }
149         else if(s[i]==')')
150         {
151             thi.a=cul();
152             thi.type=0;
153             ms.Enstack(thi);
154         }
155         else if(s[i]=='(')
156         {
157             thi.a=-1;
158             thi.type=1;
159             ms.Enstack(thi);
160         }
161         else if(s[i]=='^')
162         {
163             thi.a=0;
164             thi.type=1;
165             ms.Enstack(thi);
166         }
167         else if(s[i]=='*')
168         {
169             thi.a=1;
170             thi.type=1;
171             ms.Enstack(thi);
172         }
173         else if(s[i]=='+')
174         {
175             thi.a=2;
176             thi.type=1;
177             ms.Enstack(thi);
178         }
179         else
180         {
181             thi.a=3;
182             thi.type=1;
183             ms.Enstack(thi);
184         }
185     }
186     return cul();
187 }
188 
189 int main()
190 {
191     char a;
192     for(int i=-6;i<=6;i++)
193      num[i+6]=i;
194     while(1)
195     {
196         scanf("%c",&a);
197         if(a=='\n')
198          break;
199         if(a==' ')
200          continue;
201         else s[len]=a,len++;
202     }
203     for(int i=0;i<NUM;i++)
204      answer[i]=does(s,num[i]);
205     scanf("%d\n",&n);
206     for(int i=0;i<n;i++)
207     {
208         len=0;
209         while(1)
210         {
211             scanf("%c",&a);
212             if(a=='\n'||a=='\r')
213              break;
214             if(a==' ')
215              continue;
216             else s[len]=a,len++;
217         }
218         int mark=1;
219         for(int j=0;j<NUM;j++)
220         {
221              if(answer[j]!=does(s,num[j]))
222              {
223                  mark=0;
224                  break;
225              }
226         }
227         if(mark==1)
228          cout<<char(i+'A');
229     }
230     cout<<endl;
231     return 0;
232 }

 

 

T4篝火晚会

描述

佳佳刚进高中,在军训的时候,由于佳佳吃苦耐劳,很快得到了教官的赏识,成为了“小教官”。在军训结束的那天晚上,佳佳被命令组织同学们进行篝火晚会。一共有n个同学,编号从1到n。一开始,同学们按照1,2,……,n的顺序坐成一圈,而实际上每个人都有两个最希望相邻的同学。如何下命令调整同学的次序,形成新的一个圈,使之符合同学们的意愿,成为摆在佳佳面前的一大难题。

佳佳可向同学们下达命令,每一个命令的形式如下:

(b1, b2,... bm -1, bm)

这里m的值是由佳佳决定的,每次命令m的值都可以不同。这个命令的作用是移动编号是b1,b2,…… bm –1,bm的这m个同学的位置。要求b1换到b2的位置上,b2换到b3的位置上,……,要求bm换到b1的位置上。

执行每个命令都需要一些代价。我们假定如果一个命令要移动m个人的位置,那么这个命令的代价就是m。我们需要佳佳用最少的总代价实现同学们的意愿,你能帮助佳佳吗?

对于30%的数据,n <= 1000;

对于全部的数据,n <= 50000。

格式

输入格式

输入的第一行是一个整数n(3 <= n <= 50000),表示一共有n个同学。其后n行每行包括两个不同的正整数,以一个空格隔开,分别表示编号是1的同学最希望相邻的两个同学的编号,编号是2的同学最希望相邻的两个同学的编号,……,编号是n的同学最希望相邻的两个同学的编号。

输出格式

输出包括一行,这一行只包含一个整数,为最小的总代价。如果无论怎么调整都不能符合每个同学的愿望,则输出-1。

样例1

样例输入1[复制]

 
4
3 4
4 3
1 2
1 2

样例输出1[复制]

 
2

限制

1s

 

首先构造合法的排列,我写的连成一个图跑一遍各种判断(没想好就写调半天...),然后问题转化为用置换把1,2,3...,n转化为a1,a2,a3,...,an的最小步数。由置换的相关知识容易得到步数就是ai!=i的数的个数,但是这个题又是一个环...所以统计ai-i=x的个数,个数最多的表示从x开始的排列得到的ai=i最多。
个人觉得还是很难相到的,拿去给高一学弟讲,1min后学弟:"这个简单,balabala..."(一脸黑线= =
vijos1004
  1 #include<iostream>
  2 #include<string.h>
  3 #include<stdio.h>
  4 #include<cstdlib>
  5 #include<algorithm>
  6 #define N 50005
  7 using namespace std;
  8 int n;
  9 int beg[N];
 10 int cnt;
 11 int nxt[N];
 12 int pre[N];
 13 int number[N];
 14 int answer;
 15 int t1[N],t2[N];
 16 
 17 struct edge
 18 {
 19     int b,nxt;
 20 }E[4*N];
 21 
 22 void addedge(int a,int b)
 23 {
 24     E[cnt].b=b;
 25     E[cnt].nxt=beg[a];
 26     beg[a]=cnt;
 27     cnt++;
 28     E[cnt].b=a;
 29     E[cnt].nxt=beg[b];
 30     beg[b]=cnt;
 31     cnt++;
 32 }
 33 
 34 int make()
 35 {
 36     int now=0;
 37     nxt[now]=E[0].b;
 38     pre[E[0].b]=now;
 39     now=E[0].b;
 40     while(1)
 41     {
 42         int thi;
 43         int mark=1;
 44         for(int i=beg[now];i!=-1;i=E[i].nxt)
 45         {
 46             if(nxt[E[i].b]==now||pre[E[i].b]==now)
 47              continue;
 48             else if(pre[E[i].b]==-1)
 49             {
 50                 if(nxt[now]==-1)
 51                 {
 52                     pre[E[i].b]=now;
 53                     nxt[now]=E[i].b;
 54                     mark=2;
 55                     thi=E[i].b;
 56                 }
 57                 else
 58                 {
 59                     mark=0;
 60                     break;
 61                 }
 62             }
 63             else
 64             {
 65                 mark=0;
 66                 break;
 67             }
 68         }
 69         if(mark==1)
 70          break;
 71         if(mark==0)
 72          return 0;
 73         now=thi;
 74     }
 75     now=0;
 76     int tot=1;
 77     while(1)
 78     {
 79         number[tot]=now;
 80         tot++;
 81         now=nxt[now];
 82         if(now==0)
 83          break;
 84     }
 85     return 1;
 86 }
 87 
 88 int main()
 89 {
 90     memset(nxt,-1,sizeof(nxt));
 91     memset(pre,-1,sizeof(pre));
 92     memset(beg,-1,sizeof(beg));
 93     int a,b;
 94     scanf("%d",&n);
 95     for(int i=0;i<n;i++)
 96      scanf("%d%d",&a,&b),addedge(i,a-1),addedge(b-1,i);
 97     if(make()==0)
 98     {
 99         printf("-1\n");
100         return 0;
101     }
102     for(int i=1;i<=n;i++)
103     {
104         int t=(number[i]-i+n)%n;
105         t1[t]++;
106         answer=max(answer,t1[t]);
107         t=(number[n-i+1]-i+n)%n;
108         t2[t]++;
109         answer=max(answer,t2[t]);
110     }
111     printf("%d\n",n-answer);
112     return 0;
113 }

但是由于时间久远其实这一年的题并没有什么参考价值吧QAQ...

posted @ 2016-11-16 20:47  zyx_45889  阅读(294)  评论(0编辑  收藏  举报