T1 卖水果

难度:学过分支就能拿到满分,刚入门学过输入输出也可以得到 3030 分。

3030 分做法:根据数据范围,有 3030% 数据“保证做成果酱收益最高”,直接输出 n/10x4n/10*x*4 即可完成。或者依据另外 3030% 数据“保证做成沙拉收益最高”,直接输出 n/2yn/2*y 也可获得 3030 分。

满分做法:题目中一共有三种售卖方式,分别计算出三种方式的收益同时记录最大值输出即可,且 nn 一定是 1010 的倍数,因此也无需考虑不能整除的情况。

C++ 代码

#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 << endl;
    else if (plan2 > plan3) cout << plan2 << endl;
    else cout << plan3 << endl;
    
    return 0;
}

T2 算得分

难度:使用简单的嵌套循环,并会使用循环求解次方以及寻找最值就能拿到满分。仅仅会使用分支和单层循环可以拿到 6060 分。

6060 分做法:数据中有 3030% 保证 ni=0n_i=0,这种情况说明仅仅提交了当前这次,直接将 sis_i 加入总分即可;还有 3030% 保证 ni=10n_i=10,则可以直接按照 si7/10s_i*7/10 计算并加入总分。综上,在完成输入的同时去判断 nin_i 的是 00 还是 1010 并计算对应结果计入总分,最终输出总分,便可得到 6060 分。

满分做法:首先循环 TT 次完成输入,对于每一组 sis_inin_i,将 s7/10s*7/10 的结果与通过循环 nns=s95/100s=s*95/100 算出的结果作比较,其中较大值计入总分即可。

C++ 代码

#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 << endl;
    
    return 0;
}

T3 XAZXOJ

难度:需要学过字符串并找到正确的枚举策略可以拿到满分。

3030 分做法:依据数据中的子任务 22,有 3030% 的数据保证 ss 中仅有一个子序列是 xazxojxazxoj,因此我们只需要找到第一个 xx 的位置和最后一个 jj 的位置便能求得答案。

满分做法:枚举策略为遍历字符串,枚举出每一个 xx 为开头的包含“ xazxojxazxoj ”子序列的最短子串长度,同时记录最小值。

C++ 代码

#include <bits/stdc++.h>
using namespace std;

string s;
string t = "xazxoj";

int main()
{
    cin >> s;
    int ans = s.size();
    for (int i = 0; i < s.size(); i ++ )
    {
        if (s[i] != 'x') 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] 这个子串中存在子序列 xazxoj
                // 显然这是 i 开头最短的子串
                ans = min(ans, j - i + 1);
                break;
            }
        }
    }
    
    cout << ans << endl;
    
    return 0;
}

T4 三子棋

难度:需要熟练掌握二维数组以及枚举思想并有一定的程序优化能力。

满分做法:首先需要确定枚举的策略来确保不会重复或遗漏,对于每一个三连来说都有三个位置的棋子,即两个端点和一个中间点,那么我们可以枚举当前这个没有放棋子的位置作为端点或作为中间点能否横着、竖着或斜着构成三连。作为端点一共有8个方向可以延伸出去,即上、右上、右、右下、下、左下、左、左上,而作为中间点有4个方向可以延伸,即横、竖、左斜、右斜。对于每种情况通过下标的改变和数组调用,判断对应位置是否已落子即可记录出最终的解。

C++ 代码

#include <bits/stdc++.h>
using namespace std;

int n, m;
char g[55][55];
// 左上、上、右上、左、右、左下、下右下
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;
    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], y = j + dy[k];
                int a = i + 2 * dx[k], b = j + 2 * dy[k];
                if (g[x][y] == '#' && g[a][b] == '#')
                {
                    flag = true;
                    break;
                }
            }
            if (flag)
            {
                ans ++ ;
                continue;
            }
            // 作为中间点的四个方向
            for (int k = 1; k <= 4; k ++ )
            {
                int x = i + dx[k], y = j + dy[k];
                int a = i - dx[k], b = j - dy[k];
                if (g[x][y] == '#' && g[a][b] == '#')
                {
                    flag = true;
                    break;
                }
            }
            if (flag) ans ++ ;
        }
        
    cout << ans << endl;
    
    return 0;
}

0 comments

No comments so far...