2018年天梯赛全国总决赛
L1-049 | 天梯赛座位分配 | 20 | 743 | 2705 | 0.27 |
L1-050 | 倒数第N个字符串 | 15 | 1063 | 2299 | 0.46 |
L1-051 | 打折 | 5 | 2279 | 4590 | 0.50 |
L1-052 | 2018我们要赢 | 5 | 2299 | 3451 | 0.67 |
L1-053 | 电子汪 | 10 | 1810 | 2986 | 0.61 |
L1-054 | 福到了 | 15 | 945 | 3165 | 0.30 |
L1-055 | 谁是赢家 | 10 | 1302 | 3518 | 0.37 |
L1-056 | 猜数字 | 20 | 1134 | 3568 | 0.32 |
L2-025 | 分而治之 | 25 | 262 | 684 | 0.38 |
L2-026 | 小字辈 | 25 | 196 | 661 | 0.30 |
L2-027 | 名人堂与代金券 | 25 | 226 | 676 | 0.33 |
L2-028 | 秀恩爱分得快 | 25 | 140 | 831 | 0.17 |
L3-019 | 代码排版 | 30 | 0 | 317 | 0.00 |
L3-020 | 至多删三个字符 | 30 | 65 | 281 | 0.23 |
L3-021 | 神坛 | 30 | 148 | 997 | 0.15 |
题解(没有遵照题目集顺序):
L1-049 | 天梯赛座位分配 |
(这题的难度应当是一阶梯中最难的了吧)
先参考了一些大犇的写法:
#include<bits/stdc++.h>
using namespace std;
vector<int> m[105];
int sum=0;
struct node{
vector<int>q;
int num;
}a[105];
int main(){
int n;
cin>>n;
int x;
for(int i=1;i<=n;i++){
cin>>x;
a[i].num=x*10;
sum+=x*10;//统计总人数
}
//cout<<sum<<endl;
int id=1;
while(sum--){
for(int i=1;i<=n;i++){
if(a[i].q.size()!=a[i].num){
if(a[i].q.empty()==false&&a[i].q.back()+1==id){
a[i].q.push_back(id+1);
id+=2;
}
else{
a[i].q.push_back(id);
id++;
}
}
}
}
for(int i=1;i<=n;i++){
cout<<"#"<<i<<endl;
for(int j=0;j<a[i].q.size();j++){
if(j%10==0&&j!=0)
cout<<endl;
if(j%10!=0) cout<<" ";
cout<<a[i].q[j];
}
cout<<endl;
}
return 0;
}
这是众多写法中的一种, 其实这道模拟题第一眼看到也应该能明白是用数组解决,但是这不是一锤子买卖的问题,不要小瞧简单的数组——这背后的思维量是无穷无尽的。耗时很久我才稍稍明白大犇解决问题的思路。
就是说:我们排座位,是需要按照队的数量、学校的数量排列的,而这两种排列标准也有优先大小(肯定是先排队再排学校了,如果说一个学校的排在一起肯定是不可以的TAT)。那么题目中这句话就显得格外重要:“如果最后只剩下 1 所学校的队伍还没有分配座位,则需要安排他们的队员隔位就坐。“,也就是说这是一种特殊情况,那么我们在排序的时候,就按照这样的规律展开我们的代码:第一个学校的第一个队,插入第一个数;第二个学校的第二个队插入第二个数。。。
#1
1 4 7 10 13 16 19 22 25 28
31 34 37 40 43 46 49 52 55 58
61 63 65 67 69 71 73 75 77 79
#2
2 5 8 11 14 17 20 23 26 29
32 35 38 41 44 47 50 53 56 59
62 64 66 68 70 72 74 76 78 80
82 84 86 88 90 92 94 96 98 100
#3
3 6 9 12 15 18 21 24 27 30
33 36 39 42 45 48 51 54 57 60
也就是说,样例中除了#2中的第四行都是一般情况,只需要按照优先规则push_back就可以了。
对于特殊情况,为了造成隔一个位子的情况, 就要先检测末尾数+1是不是等于id,然后在插入的时候直接插入id+1,id自增2就可以喽。
L1-054 | 福到了 |
#include<bits/stdc++.h>
using namespace std;
int main(){
char ch;
int n;
cin>>ch>>n;
getchar();
int k=0,p=0;
int j;
int flag=1;
char a[105][105],b[105][105],c[105][105];
for(int i=0;i<n;i++){
for(int j=0;j<n;j++){
scanf("%c",&a[i][j]);
b[i][j]=a[i][j];
}
getchar();
}
for(int i=n-1;i>=0;i--){
for(int j=n-1;j>=0;j--){
if(b[k][p++]!=a[i][j])
flag=0;
c[i][j]=a[i][j];
}
p=0;
k++;
}
if(flag){
cout<<"bu yong dao le"<<endl;
for(int i=0;i<n;i++){
for(int j=0;j<n;j++){
if(a[i][j]=='@')
printf("%c",ch);
else
printf("%c",a[i][j]);
}
printf("\n");
}
}else{
for(int i=n-1;i>=0;i--){
for(int j=n-1;j>=0;j--){
if(a[i][j]=='@')
printf("%c",ch);
else
printf("%c",a[i][j]);
}
printf("\n");
}
}
return 0;
}
(当年觉得这题真的好难,现在看来的确是比较简单了,其实就是解决字符串的存储问题。在最开始思考的时候考虑最多的就是如何实现字符的替换,现在来看,只需要让有字符的按照规律输出制定字符,没有字符的位置按原图案输出就可以了)
L1-050 | 倒数第N个字符串 |
#include<bits/stdc++.h>
using namespace std;
int main(){
int l,n;
cin>>l>>n;
double X=pow((double)26,(double)l)-n;
//cout<<X+n<<endl;
int m=(int)X;
//cout<<"m="<<m<<endl;
char result[6];
int i=0;
for(int i=0;i<l;i++){
result[i]='a'+m%26;
m=m/=26;
}
for(int j=l-1;j>=0;j--)
cout<<result[j];
}
这里,我们把字母当成数字进行处理。在给出的长度为l的字符串中,每一位都有26种选择,于是就是26的l次方种字符串。我们用这个数减去输入的int型数字,得到的就是正序数字,那么我们只需要实现数字到字符的转换就可以了。
L1-051 | 打折 |
#include<iostream>
#include<cstdio>
using namespace std;
int main(){
int x,count;
scanf("%d %d",&x,&count);
double result=x*count*1.0/10;
printf("%.2f\n",result);
return 0;
}
L1-052 | 2018我们要赢 |
#include<bits/stdc++.h>
using namespace std;
int main(){
cout<<"2018"<<endl;
cout<<"wo3 men2 yao4 ying2 !"<<endl;
}
L1-053 | 电子汪 |
#include<bits/stdc++.h>
using namespace std;
int main(){
int a,b;
cin>>a>>b;
int n=a+b;
for(int i=1;i<=n;i++)
cout<<"Wang!";
cout<<endl;
}
L1-055 | 谁是赢家 |
这道题只需要把各种情况考虑清楚就可以了
#include<bits/stdc++.h>
using namespace std;
int main()
{
int pa,pb;
cin>>pa>>pb;
int t;
int a=0,b=0;
for(int i=1; i<=3; i++)
{
cin>>t;
if(t==0)
{
a++;
}
else
{
b++;
}
}
//cout<<a<<" "<<b<<endl;
if(pa>pb)
{
if(a>=1){
printf("The winner is a: %d + %d",pa,a);
}else{
printf("The winner is b: %d + %d",pb,b);
}
}
else if(pb>pa){
if(b>=1){
printf("The winner is b: %d + %d",pb,b);
}
else{
printf("The winner is a: %d + %d",pa,a);
}
}
}
L1-056 | 猜数字 |
#include<bits/stdc++.h>
using namespace std;
struct Node{
string name;
int num;
}node[10005];
int main(){
int minx=99999;
int sum=0;
int n;
cin>>n;
string str;
for(int i=0;i<n;i++){
cin>>node[i].name>>node[i].num;
sum+=node[i].num;
}
double result=sum*1.0/n/2;
for(int i=0;i<n;i++){
if(abs(node[i].num-result)<minx){
minx=abs(node[i].num-result);
str=node[i].name;
}
}
cout<<(int)result<<" "<<str<<endl;
return 0;
}
(排序都是多余的操作,其实只需要把各个人猜的数和平均数的一半进行比较,选择出差值最小的输出名字尽可以了)