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
限制
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个石子在数轴上的位置(数据保证桥的起点和终点处没有石子)。所有相邻的整数之间用一个空格隔开。
输出格式
输出只包括一个整数,表示青蛙过河最少需要踩到的石子数。
限制
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个字符,而且保证选项中总有表达式和题干中的表达式是等价的。
输出格式
输出包括一行,这一行包括一系列选项的标号,表示哪些选项是和题干中的表达式等价的。选项的标号按照字母顺序排列,而且之间没有空格。
限制
1s
题意几乎就是裸的..由于次数小于等于10,我们只需要枚10个值代入每个表达式算一算,十个值都相等就一定是等价表达式
但是代码能力拙计...也没有什么办法,这个题我的代码过了noip的数据但是没有过vijos的,而且长度和编程时间也是不尽人意...
注意:
1.由于有可能出现爆longlong,要取模(所以也最好多计算几组)
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。
限制
1s
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...