2024CSP-J复赛自我感受

今天上午,2024CSP-J第二轮认证开始了。我筹备了一个多月,就是想在第一年拿个好成绩。

可是,就是这次考试,让我对CSP有了阴影。

本来今年我是第一次考,可是差点爆零!

先看看今年的题目:

不算是太难,但对于我这种小菜来说想要拿到150分是不可能的。我不确定我的代码是否正确,但也做出来第一题。

来跟大家分享一下我差点爆零的故事:

今天上午快11:30分时,监考人员说先把放在提交栏处的文件代码拷贝出来,以免丢失,因为他要清理提交记录。但我当时在看第四题,反正我也做不出来第四题,于是我就翘着二郎腿,开始摸鱼,根本没有听监考的话。于是,待我满怀信心回到提交处,发现我的代码不见了。我满脸惊慌,连忙向监考老师示意。虽然监考老师知道后有一万个不情愿,但还是帮我从清理的那堆垃圾中找到了我的代码。吓我一跳,我还以为我又要白手起家了。

今天下午,我的老师发了题解给我,来看看题解:

poker

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

int n, ans, cnt[56 + 5], res;

int turn_1(char u)
{
    if (u == 'D')
        return 0;
    if (u == 'C')
        return 1;
    if (u == 'H')
        return 2;
    if (u == 'S')
        return 3;
}

int turn_2(char u)
{
    if (u == 'A')
        return 1;
    if (u == 'T')
        return 10;
    if (u == 'J')
        return 11;
    if (u == 'Q')
        return 12;
    if (u == 'K')
        return 13;
    return u - '0';
}

int main()
{
    cin >> n;
    for (int i = 1; i <= n; i++)
    {
        string s;
        cin >> s;
        res = turn_1(s[0]) * 13 + turn_2(s[1]);
        cnt[res]++;
    }
    for (int i = 1; i <= 52; i++)
        if (!cnt[i])
            ans++;
    cout << ans;
    return 0;
}

explore

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

int T, m, n, K, x, y, d;
int dir[4][2] = {0, 1, 1, 0, 0, -1, -1, 0};
char mm[N][N];
bool vis[N][N];

bool ok(int u, int v) // 判断位置(u,v)是否合法
{
    if (u < 1 || u > m || v < 1 || v > n)
        return 0;
    if (mm[u][v] != '.')
        return 0;
    return 1;
}

int main()
{
    cin >> T;
    while (T--)
    {
        memset(vis, 0, sizeof(vis));
        scanf("%d%d%d", &m, &n, &K);
        scanf("%d%d%d", &x, &y, &d);
        for (int i = 1; i <= m; i++)
            scanf("%s", mm[i] + 1);
        vis[x][y] = 1;
        while (K--)
        {
            int nx, ny;
            nx = x + dir[d][0];
            ny = y + dir[d][1];
            if (!ok(nx, ny))
            {
                d = (d + 1) % 4;
                continue;
            }
            x = nx, y = ny;
            vis[x][y] = 1;
        }
        int ans = 0;
        for (int i = 1; i <= m; i++)
            for (int j = 1; j <= n; j++)
                if (vis[i][j])
                    ans++;
        printf("%d\n", ans);
    }
}

sticks

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

int T, n, len;
int cnt[10] = {6, 2, 5, 5, 4, 5, 6, 3, 7, 6};

bool judge(int u, int v) // 判断用v个火柴棒拼成u个数位是否合法
{
    if (v > u * 7)
        return 0;
    if (v < u * 2)
        return 0;
    return 1;
}

void work(int now, int sum) // 目前在填第now位,火柴棒还有sum个
{
    if (!now)
        return;
    int st = 0;
    if (now == len) // 注意不能有前导零
        st = 1;
    for (int i = st; i <= 9; i++) // 尝试将i填到第now位
    {
        if (judge(now - 1, sum - cnt[i]))
        {
            printf("%d", i);
            work(now - 1, sum - cnt[i]);
            break;
        }
    }
}

int main()
{
    cin >> T;
    while (T--)
    {
        scanf("%d", &n);
        if (n == 1)
        {
            puts("-1");
            continue;
        }
        len = (n + 6) / 7; // 计算最终的数位个数
        work(len, n);
        puts("");
    }
    return 0;
}

chain

#include <bits/stdc++.h>
#define N 200100
#define M 110
using namespace std;

int T, n, K, Q, ok[M][N];
vector<int> num[N];

int main()
{
    cin >> T;
    while (T--)
    {
        memset(ok, -1, sizeof(ok));
        scanf("%d%d%d", &n, &K, &Q);
        for (int i = 1; i <= n; i++)
        {
            num[i].clear();
            int len;
            scanf("%d", &len);
            for (int j = 1; j <= len; j++)
            {
                int t;
                scanf("%d", &t);
                num[i].push_back(t);
            }
        }

        ok[0][1] = 0;
        for (int T = 1; T <= 100; T++)
        {
            for (int i = 1; i <= n; i++)
            {
                int len = 0;
                for (auto t : num[i])
                {
                    len = max(len - 1, 0);
                    if (len)
                    {
                        if (ok[T][t] == -1)
                            ok[T][t] = i;
                        else if (ok[T][t] && ok[T][t] != i)
                            ok[T][t] = 0;
                    }
                    if (ok[T - 1][t] != -1 && ok[T - 1][t] != i)
                        len = K;
                }
            }
        }
        while (Q--)
        {
            int p, q;
            scanf("%d%d", &p, &q);
            puts(ok[p][q] != -1 ? "1" : "0");
        }
    }
}

我认为,poker用字符串去重,explore用深搜,sticks用暴力枚举+找规律,chain用链表+动态规划。可是,我有一个同学第一题用了set函数,直接把我震撼到了。

首先先定义一个set函数,输入一个字符串就存进去一个,因为set函数会自动去重,所以不必要再判断重复,最后用52减去set函数中的数就行了。

我用了一点小暴力,但是放手一搏的感觉真爽(我实在做不出来,到11:30了才被迫用这个方案的)。虽然我是放手一搏,但过了我的很多样例。什么实力我不说!

总之,第一次考CSP-J复赛还是很惊险的,虽然旁边就是大佬,但看不到大佬的代码呀!

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值