S09689陈丽颖
一、题目报告
比赛时总分280分,其中第一题和第四题AC,第二题70分,第三题10分,比赛后全部AK。第二题总共有10个测试样例,我只写了7个,少写了3个,所以只得了70分。第三题一点也看不懂,直接输出样例,结果骗到了10分。
二、解题报告
T1.独木桥(bridge)
题目情况:
比赛时AC,当时我是先判断人离左端点近还是离右端点近,如果离左端点近,那么他离开独木桥就需要a[i]秒,如果离右端点近,那么他离开独木桥就需要l-a[i]秒,然后再根据他们离开独木桥的时间找最大值,最后输出就行了。
题目大意:
长度为 L米的独木桥上有 n个人,他们每个人都想以最快的时间离开危险的独木桥。已知每个人在独木桥上的行走速度为 1米 / 秒 ,每个人只要能走到独木桥的两个端点中的其中一个就可以离开独木桥。
由于独木桥的桥面宽度很窄,只能容纳一个人通过,当两个人相遇时,他们无法交错通过,只能各自调转方向,继续沿反方向行走。
给你独木桥上的人数 nn ,独木桥的长度 L, 第 i个人的初始位置到独木桥左端点的距离ai 米(每个人开始的朝向未知,但他们可以根据需要随时调转行走的方向)。
请计算出所有人同时出发,全部都离开独木桥所需的最短时间。
题目解析:
1.要判断a[i]这个人是离左端点近还是离右端点近,如果离左端点近,那么他离开独木桥就需要a[i]秒时间;如果离右端点近,那么他离开独木桥就需要l-a[i]秒时间。
2.由于独木桥的桥面宽度很窄,只能容纳一个人通过,当两个人相遇时,他们无法交错通过,只能各自调转方向,继续沿反方向行走。
正确代码:
#include<iostream>
using namespace std;
const int N=1e6+10;
int n,l;
int a[N];
int main(){
cin>>n>>l;
int cnt=0,maxx=-2147483647;
for(int i=1;i<=n;i++){
cin>>a[i];
if(a[i]<l/2){
cnt=a[i];
}
else{
cnt=l-a[i];
}
maxx=max(maxx,cnt);
}
cout<<maxx;
return 0;
}
T2、移动棋子(chess)
题目情况:
比赛时70分,因为这个题有10个样例,我只写出了7个,少写了3个,所以这道题我只得了70分。
题目大意:
一维的棋盘上有无限多个格子,每个格子都有一个编号,最中间的格子编号为 00 ,00 号格子向右依次编号为 1,2,3,… ,向左依次编号为 -1 - 2, -3,… 。
小明的目标是要将一枚棋子从 x号格子移动到 y 号格子。
每一次操作有两种选择:
操作 1:向右移动 1个格子。
操作 2:从当前棋子所在的 a号格子,直接跳到 -a号格子(如:可以从 6 直接跳到 −6 ,也可以从 −6 直接跳到6 )。
可以证明,无论整数 x和 y 的值是多少,目标总是可以实现的。
请你设计程序,帮小明计算把棋子从 x 号格子移动到 y 号格子需要的最少操作次数。
题目解析:
1.x和y不会相等,所以不会输出0。
2.如果x和y都是正数,那么向右移动 1个格子。
3.如果x是负数且y是正数且abs(x)==y 或 x是正数且y是负数且x==abs(y)。
正确代码:
#include<iostream>
#include<cmath>
using namespace std;
int main(){
int a,b;
cin>>a>>b;
if(a>b&&((a<0&&b<0)||(a>0&&b>0))){
cout<<abs(abs(a)-abs(b))+2<<endl;
}
else if((a<0&&b>0)||(a>0&&b<0)){
cout<<abs(abs(a)-abs(b))+1<<endl;
}
else{
cout<<abs(abs(a)-abs(b))<<endl;
}
return 0;
}
T3.动物园(zoo)
题目情况:
比赛时10分,当时我一看到题目描述,心想:啊?这是第三题,那第四题不得难爆了。但是!!!我直接输出样例,成功骗到了10分。
题目大意:
小明希望看到动物园内所有种类的动物,同时小明是个非常节约的孩子,他希望花最少
的钱买门票。 请你帮小明计算:他最少需要花费多少钱买门票才能看到所有种类的动物(同
一种动物他可能不止看一个)。注意:小明只能买一张门票。
题目解析:
1.注意:小明只能买一张门票。
2.小明希望看到动物园内所有种类的动物,同时小明是个非常节约的孩子,他希望花最少
的钱买门票。
3.这道题是用双指针来做,并且双指针是在同一侧。而像这样使用双指针的题还有很多,比如说:小可的正整数序列、小可的正整数序列、无重复字符的最长子串、替换后的最长重复字符、盛水最多的容器、接雨水等等。
正确代码:
#include<iostream>
using namespace std;
const int N=1e6+10;
int a[N],b[N],cnt,ans=N;
int main(){
int n,m;
cin>>n>>m;
for(int i=1;i<=n;i++){
cin>>a[i];
}
int l=1,r=1;
while(r<=n){
b[a[r]]++;
if(b[a[r]]==1){
cnt++;
}
while(b[a[l]]>=2){
b[a[l]]--;
l++;
}
r++;
if(cnt==m){
ans=min(ans,r-l);
}
}
cout<<ans*10;
return 0;
}
T4.摧毁(destroy)
题目情况:
比赛时AC,当时我是这样想的:如果这一轨道上的卫星个数大于等于c,那么就让cnt加c。否则,如果这一轨道上的卫星个数小于c,那么就让cnt加这一轨道上的卫星个数,最后在输出cnt。
题目大意:
因为一个轨道上的卫星数量是有上限的,且卫星更新换代速度很快,如果想要发射新的卫星,需要把所有旧的卫星摧毁。
人类有两种不同的武器可以摧毁卫星,具体如下(其中PW为新的能量单位):
(1)使用定点激光武器花费 1 PW
的代价摧毁任意轨道上指定的一个卫星。
(2)使用脉冲轨道武器花费 c PW
的代价把某一轨道上的所有卫星摧毁。
现在有n个旧卫星分布在不同的外轨道上,你的任务是摧毁这些旧卫星。给出这nn个卫
星的轨道编号,求将这些卫星全部摧毁的最小代价是多少?
题目解析:
1.如果这一轨道上的卫星个数大于等于c,那么就让cnt加c。
2.如果这一轨道上的卫星个数小于c,那么就让cnt加这一轨道上的卫星个数。
3.给出这n个卫星的轨道编号,求将这些卫星全部摧毁的最小代价是多少?
正确代码:
#include<iostream>
#include<cstring>
using namespace std;
const int N=1e6+10;
int t,n,c,x[N];
int a[N];
int main(){
cin>>t;
int cnt=0,ans=0;
while(t--){
memset(a,0,sizeof(a));
cin>>n>>c;
ans=0;
for(int i=1;i<=n;i++){
int l;
cin>>l;
a[l]++;
}
for(int i=1;i<=n;i++){
if(a[i]>=c){
ans+=c;
}
else{
ans+=a[i];
}
}
cout<<ans<<endl;
}
return 0;
}