1.比赛分数:
共四题,满分400,比赛中拿到20分,第一题10分,最后题每题得10分。
2.比赛过程:
第一题开始想循环求出过桥的最短时间。
第二题开始用if判断通过样例。
第三个没想到怎么做,用暴力做的。
第四题没想到怎么做,也是用暴力做的。
3.题解报告:
(1)第一题:
独木桥(bridge)
题目描述
长度为 LL 米的独木桥上有 nn 个人,他们每个人都想以最快的时间离开危险的独木桥。已知每个人在独木桥上的行走速度为 11 米 / 秒 ,每个人只要能走到独木桥的两个端点中的其中一个就可以离开独木桥。
由于独木桥的桥面宽度很窄,只能容纳一个人通过,当两个人相遇时,他们无法交错通过,只能各自调转方向,继续沿反方向行走。
给你独木桥上的人数 nn ,独木桥的长度 LL , 第 ii 个人的初始位置到独木桥左端点的距离aiai 米(每个人开始的朝向未知,但他们可以根据需要随时调转行走的方向)。
请计算出所有人同时出发,全部都离开独木桥所需的最短时间。
输入格式(输入文件为 bridge.in)
第一行一个整数 nn ,表示人数。
第二行一个整数 LL ,表示独木桥的长度(米)。
第三行是a1a1,a2a2 …anan ,其中 aiai 表示第 ii 个人初始位置到独木桥左端点 的距离。
输出格式(输出文件为 bridge.out)
输出一行一个整数,表示所有人都离开独木桥所需的最短时间。
输入样例 #1
3
10
2 6 7
输出样例 #1
4
样例一说明
说明:三个人同时出发,第一个人向左走,需要 22 秒离开桥,第二个人向右走需要44秒离开桥,第三个人向右走需要33秒离开桥。所以,44秒后,三个人都离开了独木桥。
输入样例 #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
情况:赛中10分,已补题
题意:
所以本题就找出来每个人都朝向自己离得最近的一点行走时的max。
题解:
如果每个人都朝向最近的一点走,每人的速度都是相同的,所以不会出现相遇的情况。
AC代码:
#include<bits/stdc++.h>
using namespace std;
int n,l,x;
int ans;
int main(){
cin>>n>>l;
for(int i=1;i<=n;i++){
scanf("%d",&x);
ans=max(ans,min(x,(l-x)));
}
cout<<ans;
return 0;
}
第2题:
移动棋子(chess)
题目描述
一维的棋盘上有无限多个格子,每个格子都有一个编号,最中间的格子编号为 00 ,00 号格子向右依次编号为 11,22,33,… ,向左依次编号为 −1−1, −2−2, −3−3,… 。
小明的目标是要将一枚棋子从 xx 号格子移动到 yy 号格子。
每一次操作有两种选择:
操作 11 :向右移动 11 个格子。
操作 22 :从当前棋子所在的 aa 号格子,直接跳到 −a−a 号格子(如:可以从 66 直接跳到 −6−6 ,也可以从 −6−6 直接跳到 66 )。
可以证明,无论整数 xx 和 yy 的值是多少,目标总是可以实现的。
请你设计程序,帮小明计算把棋子从 xx 号格子移动到 yy 号格子需要的最少操作次数。
输入格式(输入文件为 chess.in)
一行,两个整数 xx 和 yy , 表示要将棋子从 xx 号格子移动到 yy 号格子。
输出格式(输出文件为 chess.out)
一个整数,表示小明把棋子从 xx 号格子移动到 yy 号格子需要的最少操作次数。
输入样例 #1
10 20
输出样例 #1
10
样例一说明
说明:需要进行1010次操作11。
输入样例 #2
10 -10
输出样例 #2
1
样例二说明
需要进行1次操作2
输入样例 #3
-10 -20
输出样例 #3
12
样例三说明
说明:先进行 11 次操作 22 ,然后进行 1010 次操作 11 ,最后进行 11 次操作 22 。
数据范围
对于 30% 的数据:|x|≤100,|y|≤100 ;
对于 100% 的数据:x,yx,y都为整数;|x| ≤ 10^9,|y|≤10^9;x,yx,y不相等。
有 40% 的数据,|x|>|y|。
有 40% 的数据,|x|<|y|。
有 20% 的数据,|x|=|y|。
情况:赛中0分,已补题
题意:
用if判断出用操作几。
题解:
如果a和b同正或者同负,且a大于b时,需要先进行一次操作2,然后进行操作1,再进行操作2,
否则,如果a和b正负性不同,则需要进行一次操作2然后再进行操作1;否则,其他情况,只进行操作1即可。
AC代码:
#include<bits/stdc++.h>
using namespace std;
int main(){
long long x,y,ans;
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<<endl;
return 0;
}
第三题:
动物园
时间限制:1秒 内存限制:128M
题目描述
某动物园里有nn个场馆和mm种动物(m≤n)(m≤n)。
nn个场馆的编号分别用 1,2,3,..,n1,2,3,..,n 表示;mm种动物的编号分别用 1,2,3,..,m1,2,3,..,m 表示。每一个场馆中只饲养了一只动物,不同的场馆可能饲养着相同种类的动物。
这个动物园的门票比较特殊,游客在购买门票时必须说明要参观的场馆的起止编号aa和bb(起止编号会打印到游客购买的门票上),代表游客只能参观动物园的第aa个场馆至第bb个场馆(包含 a,ba,b)里的动物,其他的场馆不能去。门票按一个场馆十元收费。
如果你购买的门票的起止场馆编号是 33 到 88,那么你需要花 6060 元钱购买门票,只能观看3,4,5,6,7,83,4,5,6,7,8 号场馆的动物。
小明希望看到动物园内所有种类的动物,同时小明是个非常节约的孩子,他希望花最少
的钱买门票。 请你帮小明计算:他最少需要花费多少钱买门票才能看到所有种类的动物(同
一种动物他可能不止看一个)。注意:小明只能买一张门票。
输入格式(输入文件为 zoo.in)
第一行两个整数 n,mn,m,分别表示动物园内的场馆数量及动物种类数量。
第二行是 x1,x2,⋯,xnx1,x2,⋯,xn,其中xixi表示第ii个场馆中的动物种类编号。
输出格式(输出文件为 zoo.out)
一行一个整数pp,表示小明的门票费用。
输入输出样例
样例 1 输入
12 5
2 5 3 1 3 2 4 1 1 5 4 3
*样例 1 输出
60
样例 11 说明:花费最少的其中一种购票方案选择是 a=2,b=7a=2,b=7 ,表示购买场馆 2,3,4,5,6,72,3,4,5,6,7的门票,分别看到的动物是5,3,1,3,2,45,3,1,3,2,4,其中动物33小明看了两个。
数据范围
对于 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
题意:
用双指针的应用,维护最小区间长度。
题解:
这个题本是双指针的应用。首先我们有两个指针l,r ,先让l 直到r 和 r之间有 种动物,然后再 ,保证区间内有 种动物的前提下,维护最小区间长度。
AC代码:
#include<bits/stdc++.h>
#define ll long long
using namespace std;
int n,m,a[1000005],vis[1000005];
int main() {
scanf("%d%d",&n,&m);
for(int i=1; i<=n; i++) {
scanf("%d",&a[i]);
}
int l=1,r=0,cnt=0,ans=0x3f3f3f3f;
while(r<n) {
while(cnt<m&&r<n) {
r++;
vis[a[r]]++;
if(vis[a[r]]==1) {
cnt++;
}
}
while(cnt==n) {
ans=min(ans,r-l+1);
vis[a[l]]--;
if(vis[a[l]]==0) {
cnt--;
}
l++;
}
}
printf("%d\n",ans*10);
return 0;
}
第三题:
摧毁
题目描述
坐地日行八万里,巡天遥看一千河。
20772077年,人类不仅仅是赛博科技得到了发展,太空技术也已经得到了极大的发展。地球的不同外轨道上已经充斥着各种功能用途的人造卫星。因为一个轨道上的卫星数量是有上限的,且卫星更新换代速度很快,如果想要发射新的卫星,需要把所有旧的卫星摧毁。
人类有两种不同的武器可以摧毁卫星,具体如下(其中PWPW为新的能量单位):
(1)使用定点激光武器花费 1 PW
的代价摧毁任意轨道上指定的一个卫星。
(2)使用脉冲轨道武器花费 c PW
的代价把某一轨道上的所有卫星摧毁。
现在有nn个旧卫星分布在不同的外轨道上,你的任务是摧毁这些旧卫星。给出这nn个卫
星的轨道编号,求将这些卫星全部摧毁的最小代价是多少?
输入格式( 输入文件名为 destroy.in)
第一行一个正整数TT,表示测试数据组数。
接下来对于每组测试数据(注意:每组测试数据有22行数据,以下共2∗T2∗T行数据):
第一行两个正整数nn和cc表示需要摧毁的卫星数量和使用脉冲轨道武器的代价。
第二行 是x1,x2,⋯,xnx1,x2,⋯,xn,其中xixi表示第ii个卫星的轨道编号。
输出格式( 输出文件名为 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
。轨道 11 上有 22 个卫星,轨道 22 上有 33 个卫星,轨道 44 上有 22 个卫星,轨道 55 上有 33 个卫星。因此对于轨道 11、22、44、55,均使用脉冲武器各花费 1PW
的代价可全部摧毁,总的代价为 44 PW,很显然该方案为总代价最小方案。
对于第二组测试数据,使用脉冲武器的代价为 2 PW
。轨道 11 上有 11 个卫星,轨道 22 上有33 个卫星,轨道 33 上有 11 个卫星。因此,对于轨道 11 采用激光武器,轨道 22 采用脉冲武器,轨道 33 采用激光武器可全部摧毁所有卫星,总的代价为 4 PW
,很显然该方案使得总代价最小。
数据范围
对于 30% 的数据,T=1,1≤n≤10,1≤ai≤10,1≤c≤10T=1,1≤n≤10,1≤ai≤10,1≤c≤10;
对于 60% 的数据,1≤n≤103,1≤ai≤1000,1≤c≤1001≤n≤103,1≤ai≤1000,1≤c≤100;
对于 100% 的数据,1≤T≤10,1≤n≤106,1≤ai≤106,1≤c≤1001≤T≤10,1≤n≤106,1≤ai≤106,1≤c≤100, 且所有测试数据的nn加起来不超过106106
题意:
桶标记求出最少代价。
题解:
本题的意思是消灭掉所有的数字。操作是消除掉一个数字,代价为i ,第二种操作是消除掉一种数字,代价为i 。我们把所有相同的数字数量统计出来,这两种操作选择最优即可。
AC代码:
#include<bits/stdc++.h>
using namespace std;
const int N=5e6+5;
int cnt[N],t;
int main(){
cin>>t;
while(t--){
int n,c,x,ans=0;
memset(cnt,0,sizeof cnt);
cin>>n>>c;
for(int i=1;i<=n;i++){
cin>>x;
cnt[x]++;
}
for(int i=1;i<=N;i++){
ans+=min(c,cnt[i]);
}
cout<<ans<<endl;
}
return 0;
}
四.赛事总结
本次模拟赛2我应该多复习多思考多多检查。