满分400分
考试 280分
自测 280分
第一题 100分
第二题 70分
第三题 10分
第四题 100分
第一题
赛中100分
独木桥(bridge)
第一行一个整数 nn ,表示人数。
第二行一个整数 LL ,表示独木桥的长度(米)。
第三行是a1a1,a2a2 …anan ,其中 aiai 表示第 ii 个人初始位置到独木桥左端点 的距离。
输出格式(输出文件为 bridge.out)
输出一行一个整数,表示所有人都离开独木桥所需的最短时间。
输入样例 #1
3
10
2 6 7
输出样例 #1
4
样例一说明
说明:三个人同时出发,第一个人向左走,需要 2 秒离开桥,第二个人向右走需要4秒离开桥,第三个人向右走需要3秒离开桥。所以,4秒后,三个人都离开了独木桥。
输入样例 #2
7
214
11 12 7 13 176 23 191
输出样例 #2
38
数据范围
对于 50% 的数据:1≤n≤1031≤n≤103 ;
对于 100% 的数据:1≤n≤1061≤n≤106 ,1≤L≤1061≤L≤106 ,0≤ai≤L0≤ai≤L。
比赛过程中 我想的是:这道题既然没有说明方向那么就可以让每个人下桥的距离变成他离左右点的最小距离,然后最快下桥时间就是求每人距左右点的最小距离的最大值。
思路 求每人距左右点的最小距离的最大值
代码
#include<iostream>
#include<algorithm>
#include<cmath>
using namespace std;
#define ll long long
ll n,l,a[1000005];
int main() {
cin>>n>>l;
for(int i=1; i<=n; i++) {
cin>>a[i];
a[i]=min(a[i],l-a[i]);
}
sort(a+1,a+1+n);
cout<<a[n];
return 0;
}
第二题
赛中70分,已补题
移动棋子(chess)
题目描述
一维的棋盘上有无限多个格子,每个格子都有一个编号,最中间的格子编号为 0 ,0 号格子向右依次编号为 1,2,3,… ,向左依次编号为 −1,−2, −3,… 。
小明的目标是要将一枚棋子从 xx 号格子移动到 yy 号格子。
每一次操作有两种选择:
操作 11:向右移动 1 个格子。
操作 2 :从当前棋子所在的 a 号格子,直接跳到 −a 号格子(如:可以从 6 直接跳到 −6 ,也可以从 −6 直接跳到 6 )。
可以证明,无论整数 x 和 y 的值是多少,目标总是可以实现的。
请你设计程序,帮小明计算把棋子从 x 号格子移动到 y 号格子需要的最少操作次数。
输入格式(输入文件为 chess.in)
一行,两个整数 x 和 y, 表示要将棋子从 x 号格子移动到 y 号格子。
输出格式(输出文件为 chess.out)
一个整数,表示小明把棋子从 x 号格子移动到y 号格子需要的最少操作次数。
输入样例 #1
10 20
输出样例 #1
10
样例一说明
说明:需要进行10次操作1。
输入样例 #2
10 -10
输出样例 #2
1
样例二说明
需要进行1次操作2
输入样例 #3
-10 -20
输出样例 #3
12
样例三说明
说明:先进行 1 次操作2 ,然后进行 10 次操作 1 ,最后进行 1 次操作 2 。
数据范围
对于 30% 的数据:|x|≤100,|y|≤100 ;
对于 100% 的数据:x,yx,y都为整数;|x| ≤ 10^9,|y|≤10^9;x,y不相等。
有 40% 的数据,|x|>|y|。
有 40% 的数据,|x|<|y|。
有 20% 的数据,|x|=|y|。
比赛过程中 我想的是:这道题个我做过的一道题很像,那一道题是用深搜做的,所以我觉得这一题也要用递归。
错思路 用递归弄
错代码
#include<iostream>
#include<algorithm>
#include<cmath>
using namespace std;
#define ll long long
int fun(int a,int b,int cnt) {
if(a==b) return cnt;
else if(-a==b||-b==a) {
return cnt+1;
} else if(a<b) {
return fun(a+1,b,cnt+1);
} else return fun(-a,b,cnt+1);
}
int main() {
ll a,b;
cin>>a>>b;
cout<<fun(a,b,0);
return 0;
}
对思路 挨个列举每个情况
对代码
#include<iostream>
#include<algorithm>
#include<cmath>
using namespace std;
#define ll long long
int main() {
ll x,y,ans=0;
cin>>x>>y;
if(x*y<0){
ans=abs(abs(x)-abs(y))+1;
}else if(x*y>0){
if(x>y){
ans=x-y+2;
}
else if(x<y){
ans=y-x;
}
}
else{
ans=abs(x-y);
if(x>y){
ans=ans+1;
}
}
cout<<ans;
return 0;
}
第三题
赛中10分,已补题
动物园(zoo)
题目描述
某动物园里有n个场馆和m种动物(m≤n)。
n个场馆的编号分别用 1,2,3,..,n 表示;mm种动物的编号分别用 1,2,3,..,m 表示。每一个场馆中只饲养了一只动物,不同的场馆可能饲养着相同种类的动物。
这个动物园的门票比较特殊,游客在购买门票时必须说明要参观的场馆的起止编号a和b(起止编号会打印到游客购买的门票上),代表游客只能参观动物园的第aa个场馆至第b个场馆(包含 a,ba,b)里的动物,其他的场馆不能去。门票按一个场馆十元收费。
如果你购买的门票的起止场馆编号是 33到 8,那么你需要花 60元钱购买门票,只能观看3,4,5,6,7,8 号场馆的动物。
小明希望看到动物园内所有种类的动物,同时小明是个非常节约的孩子,他希望花最少
的钱买门票。 请你帮小明计算:他最少需要花费多少钱买门票才能看到所有种类的动物(同
一种动物他可能不止看一个)。注意:小明只能买一张门票。
输入格式(输入文件为 zoo.in)
第一行两个整数 n,m分别表示动物园内的场馆数量及动物种类数量。
第二行是 x1,x2,⋯,xn,其中xixi表示第ii个场馆中的动物种类编号。
输出格式(输出文件为 zoo.out)
一行一个整数pp,表示小明的门票费用。
输入输出样例
样例 1 输入
2 5
2 5 3 1 3 2 4 1 1 5 4 3
*样例 1 输出
60
样例 1 说明:花费最少的其中一种购票方案选择是 a=2,b=7 ,表示购买场馆 2,3,4,5,6,7的门票,分别看到的动物是5,3,1,3,2,4,其中动物3小明看了两个。
数据范围
对于 30% 的数据,有n≤200,m≤20n≤200,m≤20。
对于 60% 的数据,有n≤1000,m≤1000n≤1000,m≤1000。
对于 100% 的数据,有1≤n≤106,1≤xi≤m≤2×1031≤n≤106,1≤xi≤m≤2×103
比赛过程中 我想的是:这道题我不咋会所以我就想骗分
错思路 无(骗分)
错代码
#include<bits/stdc++.h>
using namespace std;
#define ll long long
ll n,m,a[1000005],minn=1e8;
int main() {
cin>>n>>m;
for(int i=1; i<=n; i++) cin>>a[i];
if(m==1) {
cout<<10;
return 0;
} else if(m==n) {
cout<<n*10;
return 0;
} else if(m==2) {
cout<<2*10;
return 0;
} else cout<<n*m;
return 0;
}
对思路 用双指针遍历整个数组,如果遍历到一个新数cnt++,否则继续。如果遍历道第m个数,就改变左端点并求最小值
对代码
#include<bits/stdc++.h>
using namespace std;
#define ll long long
ll n,m,a[1000005],vis[1000005];
int main() {
cin>>n>>m;
for(int i=1;i<=n;i++) cin>>a[i];
int l=1,r=0,ans=0x3f3f3f3f,cnt=0;
while(r<n){
while(cnt<m&&r<n){
r++;
vis[a[r]]++;
if(vis[a[r]]==1) cnt++;
}
while(cnt==m){
ans=min(ans,r-l+1);
vis[a[l]]--;
if(vis[a[l]]==0) cnt--;
l++;
}
}
cout<<ans*10;
return 0;
}
第四题
赛中100分
摧毁
时间限制:1秒 内存限制:128M
题目描述
坐地日行八万里,巡天遥看一千河。
2077年,人类不仅仅是赛博科技得到了发展,太空技术也已经得到了极大的发展。地球的不同外轨道上已经充斥着各种功能用途的人造卫星。因为一个轨道上的卫星数量是有上限的,且卫星更新换代速度很快,如果想要发射新的卫星,需要把所有旧的卫星摧毁。
人类有两种不同的武器可以摧毁卫星,具体如下(其中PWPW为新的能量单位):
(1)使用定点激光武器花费 1 PW
的代价摧毁任意轨道上指定的一个卫星。
(2)使用脉冲轨道武器花费 c PW
的代价把某一轨道上的所有卫星摧毁。
现在有n个旧卫星分布在不同的外轨道上,你的任务是摧毁这些旧卫星。给出这n个卫
星的轨道编号,求将这些卫星全部摧毁的最小代价是多少?
输入格式( 输入文件名为 destroy.in)
第一行一个正整数T,表示测试数据组数。
接下来对于每组测试数据(注意:每组测试数据有2行数据,以下共2∗T行数据):
第一行两个正整数n和c表示需要摧毁的卫星数量和使用脉冲轨道武器的代价。
第二行 是x1,x2,⋯,xn其中xixi表示第i个卫星的轨道编号。
输出格式( 输出文件名为 destroy.out)
输出TT行答案,对于每组测试数据,输出一行一个整数表示摧毁所有卫星的代价。
输入输出样例
样例 1 输入
4
10 1
2 1 4 5 2 4 5 5 1 2
5 2
3 2 1 2 2
2 2
1 1
2 2
1 2
样例 1 输出
4
4
2
2
样例说明: 对于第一组测试数据,使用脉冲武器的代价为 1 PW
。轨道 1 上有 2 个卫星,轨道 2 上有 3 个卫星,轨道 4 上有 2 个卫星,轨道 5 上有 3 个卫星。因此对于轨道 11、2、4、5,均使用脉冲武器各花费 1PW
的代价可全部摧毁,总的代价为 4 PW,很显然该方案为总代价最小方案。
对于第二组测试数据,使用脉冲武器的代价为 2 PW
。轨道 11 上有 11 个卫星,轨道 2 上有3 个卫星,轨道 3 上有 1个卫星。因此,对于轨道 11采用激光武器,轨道 2 采用脉冲武器,轨道 33采用激光武器可全部摧毁所有卫星,总的代价为 4 PW
,很显然该方案使得总代价最小。
数据范围
对于 30% 的数据,T=1,1≤n≤10,1≤ai≤10,1≤c≤10
对于 60% 的数据,1≤n≤103,1≤ai≤1000,1≤c≤1001
对于 100% 的数据,1≤T≤10,1≤n≤106,1≤ai≤106,1≤c≤100, 且所有测试数据的nn加起来不超过106
比赛过程中 我想的是:t组测试数据就用while(t--)循环输入x然后用筒标记记录每个数字出现的次数然后判断每个数字出现的次数是否大于c,是加c,否加次数
对思路 先筒标记记录每个数字出现的次数然后判断每个数字出现的次数是否大于c,是加c,否加次数
对代码
#include<bits/stdc++.h>
using namespace std;
#define ll long long
ll T,n,c,a[1000005],x;
int main() {
cin>>T;
while(T--) {
cin>>n>>c;
ll sum=0;
memset(a,0,sizeof a);
for(int i=1; i<=n; i++) {
cin>>x;
a[x]++;
}
if(n<c) {
cout<<n<<endl;
continue;
}
for(int i=1; i<=1000000; i++) {
if(a[i]<c) sum+=a[i];
else sum+=c;
}
cout<<sum<<endl;
}
return 0;
}
考后总结: 虽然这套题偏简单,态度有点不认真,考了280分还算可以。下次考试要端正态度争取考个好成绩。