语法周赛 Round 0 题解
卖水果
难度:学过分支就能拿到满分,刚入门学过输入输出也可以得到
30 分做法:根据数据范围,有 n / 10 * x * 4
即可完成。或者依据另外 n / 2 * y
也可获得
满分做法:题目中一共有三种售卖方式,分别计算出三种方式的收益同时记录最大值输出即可,且
#include <bits/stdc++.h>
using namespace std;
int n, x, y;
int a1, a2, a3, a4;
int main()
{
cin >> n >> x >> y;
cin >> a1 >> a2 >> a3 >> a4;
int plan1 = (n / 10) * 4 * x;
int plan2 = (n / 2) * y;
int plan3 = (a1 + a2 + a3 + a4) * n;
if (plan1 > plan2 && plan1 > plan3){
cout << plan1 << "\n";
}
else if (plan2 > plan3){
cout << plan2 << "\n";
}
else{
cout << plan3 << "\n";
}
return 0;
}
算得分
难度:使用简单的嵌套循环,并会使用循环求解次方以及寻找最值就能拿到满分。仅仅会使用分支和单层循环可以拿到
60 分做法:数据中有
满分做法:首先循环
#include <bits/stdc++.h>
using namespace std;
int T, s, n, sum;
int main()
{
cin >> T;
while (T--)
{
cin >> s >> n;
int base = s * 7 / 10;
for (int i = 1; i <= n; i++)
s = s * 95 / 100;
sum += max(s, base);
}
cout << sum << "\n";
return 0;
}
WOTOJO
难度:需要学过字符串并找到正确的枚举策略可以拿到满分。
30 分做法:依据数据中的子任务 2,有 wotojo
,因此我们只需要找到第一个 w
的位置和最后一个 o
的位置便能求得答案。
满分做法:枚举策略为遍历字符串,枚举出每一个 w
为开头的包含wotojo
子序列的最短子串长度,同时记录最小值。具体做法如下:
#include <bits/stdc++.h>
using namespace std;
string s , t = "wotojo";
int main()
{
cin >> s;
int ans = s.size();
for (int i = 0; i < s.size(); i++)// 注意字符串下标从0开始
{
if (s[i] != 'w') // 找到 w 才开始往后扫
continue;
int now = 1; // 下一个要查询的字符为 t[now]
for (int j = i + 1; j < s.size(); j++)
{
// 匹配上最近的一个
if (s[j] == t[now]) //当前字符匹配上之后寻找下一个字符
now++;
if (now == 6)
{
// 到 j 的位置时六个字符都找到了
// 即 s[i] ~ s[j] 这个子串中存在子序列 wotojo
// 显然这是 i 开头最短的子串
ans = min(ans, j - i + 1);
break;
}
}
}
cout << ans << "\n";
return 0;
}
三子棋
难度:需要熟练掌握二维数组以及枚举思想并有一定的程序优化能力。
满分做法:首先需要确定枚举的策略来确保不会重复或遗漏,对于每一个三连来说都有三个位置的棋子,即两个端点和一个中间点,那么我们可以枚举当前这个没有放棋子的位置作为端点或作为中间点能否横着、竖着或斜着构成三连。作为端点一共有
#include <bits/stdc++.h>
using namespace std;
int n, m;
char g[55][55];
// 从下标为 1 开始,分别记录 8 个方向的下标变化。
// 左上、上、右上、左、右、左下、下、右下。
int dx[] = {0, -1, -1, -1, 0, 0, 1, 1, 1};
int dy[] = {0, -1, 0, 1, -1, 1, -1, 0, 1};
int main()
{
cin >> n >> m;
// 为了避免减 2 造成数组越界,下标从 2 开始输入
for (int i = 2; i <= n + 1; i++)
for (int j = 2; j <= m + 1; j++)
cin >> g[i][j];
int ans = 0;
for (int i = 2; i <= n + 1; i++)
for (int j = 2; j <= m + 1; j++)
{
if (g[i][j] == '#')
continue;
bool flag = false;
// 作为端点的八个方向
for (int k = 1; k <= 8; k++)
{
int x = i + dx[k];
int y = j + dy[k];
int xx = i + 2 * dx[k];
int yy = j + 2 * dy[k];
if (g[x][y] == '#' && g[xx][yy] == '#')
{
flag = true;
break;
}
}
if (flag)
{
ans++;
continue;
}
// 作为中间点的四个方向
for (int k = 1; k <= 4; k++)
{
// 两个棋子方向正相反
int x = i + dx[k];
int y = j + dy[k];
int xx = i - dx[k];
int yy = j - dy[k];
if (g[x][y] == '#' && g[xx][yy] == '#')
{
flag = true;
break;
}
}
if (flag)
ans++;
}
cout << ans << "\n";
return 0;
}