PTA校赛算法题十道java、C++详解

目录

7-1 专1 签到

7-2 专2 令人眼花缭乱的字符串

7-3 专3 VALORANT 

7-4 专4 吃蛋糕

7-5 专5 Game 

7-6 专6 二进制回文串 

7-7 专7 度假

7-8 专8 括号匹配Plus 

7-9 专9 生成最少叶子树

7-10 专10 禁止超速


这篇文章是基于我们前不久的校赛写的,校赛给的题解都是C++,我很想写一份完整的java版本,但是能力不够,大家可以看看逻辑,感兴趣的朋友可以写一份java题解在评论区,我替你交一下再来回复你你是不是满分通过了的具体情况。很希望有喜欢刷题的小伙伴和我交流Java版的题解。在我学成归来后,我会把这篇文章出一份完全的java题解。

 7-1 专1 签到

欢迎来2023年程序设计竞赛签到。输入正整数n,请你输出n遍2023。

输入格式:

一个正整数n

输出格式:

输出n遍2023,一个数占一行,结尾没有空行。

#include<bits/stdc++.h>
using namespace std;
int main (){
int n;
cin>>n;
for(int i=1;i<n;i++){
cout<<"2023\n";
}
cout<<"2023";
return 0;
}

不知道为什么,这道题同样的逻辑思路Java得到的分就不全面或者说超出运行时间,C和C++就满分过了。希望有知道的大佬评论区解答一下。 

7-2 专2 令人眼花缭乱的字符串

请你来帮小X做一个简单的工作,那就是:帮他数一数给出的字符串里面,出现了多少次“HEBAU”。


注:五个字母连续排列才能算作出现一次,忽略大小写!!!

输入格式:

输入只有一行字符串(可能包含空格)。

输出格式:

只需要输出“HEBAU”出现的次数即可。

输入样例1:

HEBAUhebauHeBau

输出样例1:

3

输入样例2:

HEbauLJY,heBauEuzer。hebauGS HEBAU

输出样例2:

4

代码长度限制

16 KB

时间限制

400 ms

内存限制

64 MB

import java.util.Scanner;

public class Main {
    public static void main(String[] args) {
        Scanner input = new Scanner(System.in);
        String str = input.nextLine().toUpperCase(); // 将输入的字符串转换为大写
        int count = 0;
        
        for (int i = 0; i <= str.length() - 5; i++) {
            if (str.substring(i, i + 5).equals("HEBAU")) {
                count++;
            }
        }
        
        System.out.println(count);
    }
}

7-3 专3 VALORANT 

这道题我非常想用java写,但是无法运行成功,希望有感兴趣的大佬能用Java写一写,我可以复制到PTA帮你运行看能否满分通过。

我们的好朋友cyp最近一些日子里开始沉迷于瓦洛兰特,但他最近有些许的忙碌,总是无暇顾及游戏,但他一旦有时间,肯定是会来上一局的。


下面给出cyp一天的事务安排时间表(从凌晨0:00到午夜23:59,给出的时间段都是有事务在身的,表上没写的时间即为空闲时间)。
假设空闲时间不低于60min,他就可以来一局紧张刺激的瓦洛兰特(并且同一段空闲时间他不会玩第二局游戏),请你帮他算算,这一天可以打多少局VALORANT。

输入格式:

输入在一行中给出1个不超过1000的整数A,表示cyp今天安排了n件事务要做。
接下来n行,给出每件事务的工作时间(从早到晚一次给出,无重复时间段)。

输出格式:

输出一行,只需要输出cyp今天可以玩几局VALORANT即可

输入样例:

在这里给出一组输入。例如:

8
00:00:00 - 01:00:05
01:00:05 - 04:30:00
05:30:00 - 06:30:00
06:30:00 - 07:10:58
07:10:59 - 08:00:00
08:00:00 - 09:00:00
13:00:00 - 18:00:00
18:00:00 - 19:00:00

输出样例:

在这里给出相应的输出。例如:

3

代码长度限制

16 KB

时间限制

400 ms

内存限制

64 MB

#include<stdio.h>
int main()
{
int start=0,end=0;
int n;//几个时间段
scanf("%d",&n);
int s1,s2,s3,e1,e2,e3;
int miao;
int m=0;
while(n--)
{
scanf("%d:%d:%d - %d:%d:%d",&s1,&s2,&s3,&e1,&e2,&e3);
end=s1*3600+s2*60+s3;
if(end-start>=60*60)
{
m++;
}
start=e1*3600+e2*60+e3;
}
if(23*3600+59*60+59-start>=3600)
{
m++;
}
printf("%d",m);
return 0;
}

 7-4 专4 吃蛋糕

ACM俱乐部的xzh大佬过生日了,但他必须且只能吃大小为 K 个单位的蛋糕。由于生日蛋糕的规格有限,现在你只能选择一块大小为 2 的非负整数幂(即 1,2,4,8,16,⋯)的蛋糕进行购买。
为了满足xzh的需求,可以采取对半切割的方式,将一块大小为 N 个单位的蛋糕切成两块大小为 2N​​ 个单位的蛋糕。
由于资金有限,你需要求出所需的蛋糕大小的最小值和最小切割次数。

输入格式:

第一行,一个正整数 K,表示xzh所需的蛋糕大小。

输出格式:

输出两个整数,分别表示蛋糕大小的最小值和所需的最少切割次数。

输入样例:

7

输出样例:

8 3

样例说明

获得7个单位的蛋糕至少需要大小为8的蛋糕,首先切一刀得到两个4个单位的蛋糕,将一个4个单位的蛋糕切一刀获得两个2个单位的蛋糕,将一个两个单位的蛋糕切一刀获得两个1个单位的蛋糕。最终K=7=4+2+1。

数据范围

对于 100% 的数据,1≤K≤1×106。

代码长度限制

16 KB

时间限制

400 ms

内存限制

64 MB

#include<bits/stdc++.h>
using namespace std;
int main(){
int k, sum = 1, cnt = 0;
cin>>k;
while(sum < k)sum *= 2, cnt++;
cout<<sum<<" ";
while(k % 2 == 0)k /= 2, cnt--;
cout<<cnt;
return 0;
}

7-5 专5 Game 

聪明的LJY发明了一个小游戏,他在地上花了n个格子里面有数字的格子,所有格子从左到右依次排列。

规则:
(1)玩家可以选择任意一个位置,并走到这个格子上。
(2)玩家需要根据自己脚下格子中的数字向右走这个数字个数的格子。
(3)当走过最后一个格子时游戏结束。
(4)玩家所经过(停留过的格子)数字的总和为游戏得分,包含起始位置。

作为发明这个游戏的发明者,LJY不想自己输给其他玩家,请你帮助他得到这个游戏最高的分数。

输入格式:

每个测试用例的第一行包含一个整数n(1≤n≤2×106) ———— 数组 a 的长度。
接下来一行包含n个整数a1​,a2​,…,an​(1≤ai​≤109) ———— 数组 a 的元素。

输出格式:

输出一个数字 ———— 表示LJY可以获得的最大得分。请注意,LJY可以选择任何1到n之间的起始位置,以最大化他的结果。

输入样例:

在这里给出一组输入。例如:

5
7 3 1 2 3

输出样例:

在这里给出相应的输出。例如:

7

###说明

n=5 且 a = [7,3,1,2,3],则可能的选项如下:
LJY选择 i=1。游戏过程:i=1⟶+7​8。游戏的得分是:a1​=7。
LJY选择 i=2。游戏过程:i=2⟶+3​5⟶+3​8。游戏的得分是:a2​+a5​=6。
LJY选择 i=3。游戏过程:i=3⟶+1​4⟶+2​6。游戏的得分是:a3​+a4​=3。
LJY选择 i=4。游戏过程:i=4⟶+2​6。游戏的得分是:a4​=2。
LJY选择 i=5。游戏过程:i=5⟶+3​8。游戏的得分是:a5​=3。

代码长度限制

16 KB

时间限制

400 ms

内存限制

64 MB

#include <bits/stdc++.h>
using namespace std;
#define qc std::ios::sync_with_stdio(0);
long long a[2000001];
long long dp[2000001];
int main() {
qc;
cin.tie(0);
int n;
long long ans = 0;
cin >> n;
for (int i = 1; i <= n; i++) {
cin >> a[i];
}
for (int i = n; i >= 1; i--) {
if (i + a[i] <= n)
dp[i] = a[i] + dp[i + a[i]];
else
dp[i] = a[i];
ans = max(ans, dp[i]);
}
cout << ans << endl;
}

7-6 专6 二进制回文串 

这是一道思维题。
一个长度为 n 的二进制字符串 s (只含 0,1)。一个数字 x,如果存在长度为 n 并且含有 x 个 1 的二进制字符串 l ,使得 si​⊕li​ 为回文串(⊕ 为异或符号,1⊕1=0 ,0⊕0=0,0⊕1=1),则称这个数字 x 是 good 数字。
输出长度为 n+1 的二进制字符串 t ,如果 i 是 good 数字,则 ti​为1,否则 ti​ 为 0 。

输入格式:

每个测试包含多个测试用例。
第一行包含测试用例的数量 t (1≤t≤105)。
其后是每个测试用例的描述。
每个测试用例的第一行包含一个整数 n (1≤n≤105)。
每个测试用例的第二行包含一个长度为 n 的二进制字符串 s 。
保证所有测试用例中 n 的总和不超过105。

输出格式:

对于每个测试用例,输出一行一个长度为 n+1 的二进制字符串的答案。

输入样例:

在这里给出一组输入。例如:

4
6
101011
4
1010
8
10001101
1
1

输出样例:

在这里给出相应的输出。例如:

0010100
00100
001010100
11

说明

第一个示例。
t2​=1 ,我们可以选择 l=010100,然后字符串 s 变成 111111,这是一个回文串。
t4​=1 ,我们可以选择 l=101011。
对于所有其他 i ,都没有对应的 l,所以剩下的符号是 0 ,输出 0010100。

代码长度限制

16 KB

时间限制

400 ms

内存限制

64 MB

#include<bits/stdc++.h>
using namespace std;
int T,n,len,d,bd,ans[100005];
char ch[100005];
int main()
{
scanf("%d",&T);
while(T--)
{
scanf("%d%s",&n,ch+1),d=bd=0;
for(int i=0;i<=n;++i) ans[i]=0;
for(int i=1;i*2<=n;++i)
{
if(ch[i]==ch[n+1-i]) ++d;
else ++bd;
}
for(int i=0;i<=d;++i)
{
ans[bd+i*2]=1;
if(n%2) ans[bd+i*2+1]=1;
}
for(int i=0;i<=n;++i)
{
cout<<ans[i];
}
cout<<endl;
}
return 0;
}

 7-7 专7 度假

ML同学来到野外准备度过难得的假期。“ML,15分钟后来开会!”。雅兴被电话打断了的ML同学只好朝学校跑去。他跑到学校需要过一条河,河的宽度为L,但是唯一的桥离他非常远,因此他必须想其他的办法过河。幸运的是,河中有许多半径不同的圆形荷叶(可能会有重叠),ML可以踩着这些荷叶跳到河对岸去。

我们可以在这条河中建立直角坐标系,在坐标系中,ML同学所在一侧河岸的纵坐标y=0,学校一侧河岸的纵坐标y=L。ML通过观察得到了所有荷叶中心的坐标以及荷叶的半径,且已知他可以跳K单位长度。

如果两片荷叶之间的最短距离小于等于K,那他就可以在这两片荷叶之间跳跃;如果有一片荷叶距河岸的最短距离小于等于K,那他就可以在河岸和这片荷叶之间跳跃;ML在河岸上可以随意移动。问ML同学最终能不能到达对岸(赶上开会)。

画图4_17(1).jpg

输入格式:

每个输入文件包含多组数据。
第一行,包含一个正整数 T,代表该输入文件中所含的数据组数。
接下来是 T 组数据,每组数据的格式如下: 第一行包含三个正整数 N,L,K,两个数之间以一个空格分开,分别代表河流中荷叶的数量,河流的宽度和ML同学可以跳跃的距离。
接下来的 N 行,每行包含三个整数 x,y,r,两个数之间以一个空格分开,表示荷叶中心坐标为 (x,y),半径为r。

输出格式:

T 行,分别对应 T 组数据的答案,如果在第 i 组数据中,ML 能到达河对岸,则输出 Yes,如果不能,则输出 No

输入样例:

在这里给出一组输入。例如:

3
1 4 1
2 2 1
1 5 1
2 2 1
3 10 2
1 4 2
4 2 1
6 7 2

输出样例:

在这里给出相应的输出。例如:

Yes
No
Yes

数据范围

对于 20% 的数据,T=1,1≤L,K≤104,坐标的绝对值不超过 104。
对于 100% 的数据,1≤N≤1×103,1≤L,K≤109,T≤20,坐标的绝对值不超过 109。

代码长度限制

16 KB

时间限制

1000 ms

内存限制

250 MB

#include<bits/stdc++.h>
using namespace std;
#define N 1006
int vis[N], ans, n;
double k, l;
struct node{
double x, y, r;
}a[N];
double len(double x1, double y1, double x2, double y2){
return sqrt((x1-x2)*(x1-x2)+(y1-y2)*(y1-y2));
}
void init(){
memset(vis, 0, sizeof(vis));
memset(a, 0, sizeof(a));
ans = 0;
}
void dfs(int x){
if(a[x].y+a[x].r+k >= l){
ans = 1;
return;
}
vis[x] = 1;
for(int i=1;i<=n;i++){
if(vis[i]) continue;
if(len(a[x].x,a[x].y,a[i].x,a[i].y) <= a[x].r+a[i].r+k)
dfs(i);
}
}
int main(){
ios::sync_with_stdio(false);
cin.tie(0);
int t;
cin>>t;
while(t--){
init();
cin>>n>>l>>k;
for(int i=1;i<=n;i++)
cin>>a[i].x>>a[i].y>>a[i].r;
for(int i=1;i<=n;i++)
if(a[i].y <= k+a[i].r)
dfs(i);
if(ans) cout<<"Yes\n";
else cout<<"No\n";
}
return 0;
}

7-8 专8 括号匹配Plus 

在C语言中,我们会用到三种括号:圆括号 (),方括号 [] 和花括号 {} 。同学们想必都被编译时括号不匹配的提示折磨过,于是Azure学长为大家发明了一种万能括号,其中,万能左括号用 < 表示,而万能右括号用 > 表示。
万能括号可以与任意一个最近的一个未配对的相反方向括号进行配对,如在以下符号序列中:{[()>},最中间的圆括号正常配对,而方括号 [ 与万能括号 > 配对,最后两个花括号正常配对。

下面请你编写一个程序,用来判断所给字符串中的括号是否匹配

输入格式:

第一行输入一个数字n(1≤n≤100),表示n组数据。
接下来n行,每行输入一个字符串,判断其中出现的括号是否匹配。其中,每个字符串的长度不超过1000且不为空串。

输出格式:

对每一组输入,在一行内输出是否括号匹配。若匹配则输出YES,反之输出NO

输入样例:

在这里给出一组输入。例如:

3
int main()<printf("Hello, World!");}
{{scanf("%d",&n);}}}
int add(int a,int b){int c = a + b;return c;)

输出样例:

在这里给出相应的输出。例如:

YES
NO
NO

代码长度限制

16 KB

时间限制

400 ms

内存限制

64 MB

#include <iostream>
#include <stack>
using namespace std;
int main()
{
int n;
cin >> n;
getchar();
while (n--)
{
string str;
getline(cin, str);
stack<int> st;
bool flag = false;
for (int i = 0; str[i] != '\0'; i++)
{
if (str[i] == '(' || str[i] == '[' || str[i] == '{' ||
str[i] == '<')
{
st.push(str[i]);
}
else if (str[i] == '>' || str[i] == ')' || str[i] ==
']' || str[i] == '}')
{
if (st.empty())
{
printf("NO\n");
flag = true;
break;
}
if (str[i] == '>')
{
st.pop();
}
else if (str[i] == ')' && (st.top() == '(' ||
st.top() == '<'))
{
st.pop();
}
else if (str[i] == ']' && (st.top() == '[' ||
st.top() == '<'))
{
st.pop();
}
else if (str[i] == '}' && (st.top() == '{' ||
st.top() == '<'))
{
st.pop();
}
else
{
printf("NO\n");
flag = true;
break;
}
}
}
if (flag)
continue;
if (st.empty())
{
printf("YES\n");
}
else
{
printf("NO\n");
}
}
return 0;
}

这道题我做过类似的,和这个题解思路不一样,我们可以在栈中存入与左括号相反的右括号,遇到右括号再对比栈顶元素是不是一样,感觉更简单易懂。

7-9 专9 生成最少叶子树

给定一个具有 n 个顶点的树。顶点 1 为根。在一次操作中,你可以选择任何一个芽及其所有孩子,将它们重新悬挂到树的任何其他顶点上。通过执行此操作,你会删除连接芽和其父节点的边,并选择一个树上的顶点,在芽和所选的顶点之间添加一条边。所选的顶点不能是芽本身或其任何孩子。芽的所有孩子仍然与芽相连。

如果一个顶点没有孩子,则它是"叶子"。
如果一个顶点满足以下三个条件,我们称之为"芽":
(1) 不是根
(2) 至少有一个孩子
(3) 所有孩子都是叶子

在可以进行任意次上述操作的情况下(可能为零次),该树可能获得的叶子的最小数量是多少?

输入格式:

输入包含多个测试用例。第一行包含一个整数 t(1≤t≤104) —测试用例的数量。接下来是每个测试用例的描述。
每个测试用例的第一行包含一个整数 n(2≤n≤2×105) 给定树中顶点的数量。
接下来的 n−1 行每行包含两个整数 u 和 v(1≤u , v≤n , u=v),表示树中顶点 u 和 v 之间存在一条边。
保证给定的图是一棵树。
保证所有测试用例中 n 的总和不超过 2×105。

输出格式:

对于每个测试用例,输出一个整数 —— 经过一些操作后可能获得的叶子的最小数量。

输入样例:

在这里给出一组输入。例如:

3
7
1 2
1 3
1 4
2 5
2 6
4 7
2
1 2
7
7 3
1 5
1 3
4 6
4 7
2 1

输出样例:

在这里给出相应的输出。例如:

2
1
2

说明

在第一个测试用例中,树如下所示:
 

a8ab420b7ca4f310a11b4e815d2ee260498563d1.png


首先,你可以选择一个芽顶点 4 并将其悬挂到顶点 3。然后,你可以选择一个芽顶点 2 并将其悬挂到顶点 7。结果,你将得到以下具有 2 个叶子的树:
 

8b1cc9156e6793bcb9c75ddeca58490c5113c1cd.png


这是可能获得的最小叶子数。

代码长度限制

16 KB

时间限制

400 ms

内存限制

64 MB

#include<bits/stdc++.h>
using namespace std;
typedef long long ll;
#define fi first
#define se second
#define pb push_back
#define MP make_pair
const int inf = 1e9 + 10;
const int N = 2e5 + 10;
int n,ans;
vector<int> g[N];
int dfs(int u, int fa)
{
int sum = 0;
for(int i=0;i<g[u].size();i++)
{
int v = g[u][i];
if(v == fa) continue;
sum += dfs(v, u);
}
if(sum == 0) return 1;
else
{
ans += sum - 1;
return 0;
}
}
int main()
{
int t;
scanf("%d",&t);
while(t--)
{
ans = 1;
scanf("%d",&n);
for(int i=1;i<=n;i++) g[i].clear();
for(int i=1;i<n;i++)
{
int u,v;
scanf("%d%d",&u,&v);
g[u].pb(v);
g[v].pb(u);
}
dfs(1, 0);
printf("%d\n",ans);
}
return 0;
}

 7-10 专10 禁止超速

LZY大佬不想上学了,他打算自驾回家。从大学到LZY家有许多条道路,每条路上都有特定的限速,不幸的是,有些路上的限速标志丢失了,因此LZY不知道应该开多快,一种可行的方案是按照原先的速度行驶
LZY有一张城市交通路线地图,包含道路和路口的信息,每条道路是有向的,连接了两个路口A和B,A和B之间最多仅有一条道路,在道路起点处放置有一块限速标识(也可能丢失了)。身为一个老司机,LZY的行驶不受道路堵塞的影响,并且可以在瞬间完成加速和减速。当然,一定不能超过当前路段的限速。请你帮LZY大佬计算出他回家所需的最短时间是多少。

输入格式:

第一行是 3 个整数 N,M和 D,N表示路口的数目,用 1到N 标记。M 是道路的总数,D 表示LZY的目的地。
接下来的 M 行,每行描述一条道路,每行有 4 个整数 X (1≤X≤N),Y (1≤Y≤N),L (0≤L≤1000) 和 V(0≤V≤250),这条路是从 X 到 Y 的,长度为 L,速度限制是 V。如果 V 是 0,表示这条路的限速未知。
如果 V 不为 0,则经过该路的时间 T=VL​,否则 T=Vorg​L​​,Vorg​ 是你到达该路口前的速度。LZY从1出发,开始时的速度为 70

输出格式:

输出仅一个数,表示LZY从 1 到 D 所需要的最短时间,答案保留两位小数。

输入样例:

6 15 2
1 2 68 25
1 3 50 30
1 6 101 0
2 2 77 70
2 4 42 35
3 1 22 0
3 2 86 40
3 4 23 0
3 5 40 45
4 2 14 64
4 6 23 0
5 2 8 95
6 2 84 0
6 3 64 90
6 4 40 36

输出样例:

2.63

数据范围

对于 20% 的数据,V=0。
对于 100% 的数据,2≤N≤150,0≤L≤1000,1≤V≤250。

代码长度限制

16 KB

时间限制

400 ms

内存限制

64 MB

#include<bits/stdc++.h>
using namespace std;
#define N 155
#define V 255
int head[N], nex[N*N], to[N*N], speed[N*N], len[N*N], cnt = 0;
int vis[N][V]={0};
double d[N][V];
int n, m, t;
priority_queue< pair< double,pair<int,int> > >q;
void add(int x, int y, int l, int v){
nex[++cnt] = head[x];
head[x] = cnt;
to[cnt] = y;
speed[cnt] = v;
len[cnt] = l;
}
void dijkstra(){
for(int i=0;i<=n;i++){
for(int j=0;j<=250;j++){
d[i][j] = 0x3f3f3f3f;
}
}
d[1][70] = 0;
q.push(make_pair(0, make_pair(1, 70)));
while(q.size()){
int ov = q.top().second.second;
int u = q.top().second.first;
q.pop();
if(vis[u][ov])continue;
vis[u][ov] = 1;
for(int i=head[u];i;i=nex[i]){
int v = to[i], l = len[i], nv = speed[i];
if(nv == 0) nv = ov;
if(d[v][nv] > d[u][ov] + (double)l/(double)nv){
d[v][nv] = d[u][ov] + (double)l/(double)nv;
q.push(make_pair(-d[v][nv], make_pair(v, nv)));
}
}
}
}
int main(){
int x, y, v, l;
ios::sync_with_stdio(false);
cin.tie(0);
cin>>n>>m>>t;
for(int i=1;i<=m;i++){
cin>>x>>y>>l>>v;
add(x, y, l, v);
}
dijkstra();
int ansv = 0;
double minn = 0x3f3f3f3f;
for(int i=0;i<=250;i++){
if(d[t][i] < minn){
minn = d[t][i];
ansv = i;
}
}
printf("%.2lf", d[t][ansv]);
return 0;
}

 最后,再次希望能有感兴趣的朋友写一写java题解,我帮你提交评分,一起共同进步!

  • 33
    点赞
  • 25
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值