Skip to content

泉州一中信息学Blog

信息学奥赛技术分享博客

  • 登录
  • 小学oj
  • 中学oj
  • 测试页面1
  • Toggle search form

NFLS-DAY 6

Posted on 2023年8月7日2023年8月7日 By 张, 高畅 NFLS-DAY 6无评论

T0

准确的说,昨天(DAY 6)是放假
但是blog如果不连续会不会被当成少写一篇而被惩罚呢?(bushi

T1

有辆公交车,它可以承载35人,包括一个司机。车子最后一排有4个座位,其他10排都有3个座位。每个上车的人,都会先往左边坐(司机所在的那侧)。现在告诉你,有多少人在车上,绘制车内情况。

又是可爱的签到题,但是有点不可爱。
注意一些细节,以及是从车后到车前去填满,不过题目描述确实有那么一点点敷衍。

#include <bits/stdc++.h>
using namespace std;
int n;
int main() {
    scanf("%d", &n);
    printf("+------------------------+\n");
    for (int i = 1; i <= 4; i++) {
        printf("|");
        for (int j = 1; j <= 11; j++) {
            int x;
            if (j == 1)
                x = i;
            else
                x = 4 + 3 * (j - 2) + (i == 4 ? 3 : i);
            if (i == 3 && j > 1)
                printf("..");
            else {
                if (x <= n)
                    printf("O.");
                else
                    printf("#.");
            }
        }
        if (i != 3)
            printf("|");
        else
            printf(".");
        if (i == 1)
            printf("D");
        else
            printf(".");
        printf("|");
        if (i == 1 || i == 4)
            printf(")");
        puts("");
    }
    printf("+------------------------+\n");
    return 0;
}

T2

猜数字游戏啦!给你如下四种提示:
(1)这个数严格大于x吗?
(2)这个数严格小于x吗?
(3)这个数大于等于x吗?
(4)这个数小于等于x吗?
每个提示,都会给出相应的答案,yes或者no。
如果有多个数满足条件,输出最小的。如果不存在这样的数,输出“Impossible”。

这题不知道对边界判定的是不是很严,如果很严,确实是一道有点细节的题。
对于’N’的情况,只要将其转换为本式子的“反义”。(eg:" ">=")
然后记录一下符号,对于边界进行判断就可以了。

#include <bits/stdc++.h>
using namespace std;
int n, l = -2e9, lop = -1, r = 2e9, rop = -1;
unordered_map<string, int> mp;
int main() {
    cin >> n;
    mp[">"] = 0;
    mp["<"] = 1;
    mp["<="] = 2;
    mp[">="] = 3;
    while (n--) {
        string sign, answer;
        int x;
        cin >> sign >> x >> answer;
        int t = mp[sign];
        if (answer == "N")
            t = (((t - 2) % 4) + 4) % 4;
        if (!t || t == 3) {
            if (l < x || (!t && l == x)) {
                l = x;
                lop = t;
            }
        } else {
            if (x < r || (t == 1 && x == r)) {
                r = x;
                rop = t;
            }
        }
    }
    int x = l, y = r;
    if (!lop)
        x++;
    if (rop == 1)
        y--;
    if (x <= y) {
        if (l == -2e9)
            printf("-2000000000");
        else
            printf("%d\n", x);
    } else
        printf("Impossible\n");
    return 0;
}

T3

学完Fibonacci序列,YY觉得数字太单调了,她打算用S[n]=S[n-2]+S[n-1]的递推式去操作字符串。如果S[0]=AC,S[1]=ACB,则S[2]=ACACB。现在YY有两个字符串s[0]和s[1],她想知道,s[n]中包含多少个”AC”串。

首先提前声明,我没有改动题面。
此题就是一个递推,但显然只记录本串中含有的"AC"的个数显然不行。(eg:s[0]="AA",S[1]="CC",S[2]="AACC")
因此我们再记录收尾,在做递推时检查收尾是否能够拼接成为"AC",然后计入答案。

#include <bits/stdc++.h>
using namespace std;
const int N = 50;
struct node {
    char first, last;
    int cnt;
} s[N];
int n;
string s0, s1;
int main() {
    cin >> s0 >> s1 >> n;
    for (int i = 0; i < s0.size() - 1; i++) {
        if (s0[i] == 'A' && s0[i + 1] == 'C')
            s[0].cnt++;
    }
    for (int i = 0; i < s1.size() - 1; i++) {
        if (s1[i] == 'A' && s1[i + 1] == 'C')
            s[1].cnt++;
    }
    s[0].first = s0[0];
    s[0].last = s0[s0.size() - 1];
    s[1].first = s1[0];
    s[1].last = s1[s1.size() - 1];
    for (int i = 2; i <= n; i++) {
        s[i].cnt = s[i - 2].cnt + s[i - 1].cnt + ((s[i - 2].last == 'A' && s[i - 1].first == 'C') ? 1 : 0);
        s[i].first = s[i - 2].first;
        s[i].last = s[i - 1].last;
    }
    printf("%d", s[n].cnt);
    return 0;
}

T4

小王考入了大学,开学前需要去医院体检.
体检一共有N个项目,每个项目检查处都排起了队伍,并且人越来越多.
他一眼就发现,对于第i个项目,如果立即去排队,需要ai秒才能完成;
如果先做其他检查,在t秒后再来,那么要再多等上bi*t秒.
请你帮他规划,如何安排N个项目的顺序,才能尽早完成所有检查.

首先看到这题肯定是DP,然后发现自己不会写需要记录每个项目的使用情况,真的要写的话,空间直接爆掉。
因此考虑这题不是DP,而是和DP在某些题目长得很像的贪心。
考虑对于任意两项i,j。
不考虑前面的几项,若先i再j比先j再i所用时间短,则说明,i排序后在j前面。
推导sort所用的cmp函数,有:
a[i]+(a[i])×b[j]+a[j] < a[j]+(a[j])×b[i]+a[i]
因此:
a[i]×b[j] < a[j]×b[i]

T5

推箱子应该算是一个家喻户晓的游戏了,这次你的任务就是用电脑算出如何移动人物,完成推箱子。
为了使问题简化,数据中只有3个箱子和3个洞。
注:人一次只能推动一个箱子,箱子推到洞上后不会消失,还可以被推出去,只有当三个箱子同时在洞中时,游戏结束

看起来NFLS的出题人非常喜欢让我们写搜索,而且还是很复杂的DFS/BFS
并且这一题用来记录状态的st数组也开得有点超出想象力,你敢相信开8维数组?
注:似乎只能使用这种方式,map会导致最后两个点超时。
实在是佩服出题人。

#include <bits/stdc++.h>
using namespace std;
const int N = 9;
const int dx[4] = { 0, -1, 0, 1 };
const int dy[4] = { -1, 0, 1, 0 };
int n, m, st[N][N][N][N][N][N][N][N];
typedef pair<int, int> PII;
typedef pair<pair<PII, PII>, pair<PII, PII> > state;
#define x first
#define y second
char Map[N][N];
int check(PII box1, PII box2, PII box3) {
    if (Map[box1.x][box1.y] == '@' && Map[box2.x][box2.y] == '@' && Map[box3.x][box3.y] == '@')
        return 1;
    else
        return 0;
}
int bfs(PII p, PII box1, PII box2, PII box3) {
    queue<state> q;
    st[p.x][p.y][box1.x][box1.y][box2.x][box2.y][box3.x][box3.y] = 1;
    q.push({ { p, box1 }, { box2, box3 } });
    while (q.size()) {
        state u = q.front();
        q.pop();
        PII p = u.x.x, box1 = u.x.y, box2 = u.y.x, box3 = u.y.y;
        if (check(box1, box2, box3))
            return st[p.x][p.y][box1.x][box1.y][box2.x][box2.y][box3.x][box3.y] - 1;
        for (int i = 0; i < 4; i++) {
            int nx = p.x + dx[i], ny = p.y + dy[i];
            if (1 <= nx && nx <= n && 1 <= ny && ny <= m && Map[nx][ny] != '#') {
                if (nx == box1.x && ny == box1.y) {
                    int mx = nx + dx[i], my = ny + dy[i];
                    if (1 <= mx && mx <= n && 1 <= my && my <= m &&
                        !((mx == box1.x && my == box1.y) || (mx == box2.x && my == box2.y) ||
                          (mx == box3.x && my == box3.y)) &&
                        Map[mx][my] != '#') {
                        state ne = { { { nx, ny }, { mx, my } }, { box2, box3 } };
                        if (!st[nx][ny][mx][my][box2.x][box2.y][box3.x][box3.y]) {
                            st[nx][ny][mx][my][box2.x][box2.y][box3.x][box3.y] =
                                st[p.x][p.y][box1.x][box1.y][box2.x][box2.y][box3.x][box3.y] + 1;
                            q.push(ne);
                        }
                    }
                } else if (nx == box2.x && ny == box2.y) {
                    int mx = nx + dx[i], my = ny + dy[i];
                    if (1 <= mx && mx <= n && 1 <= my && my <= m &&
                        !((mx == box1.x && my == box1.y) || (mx == box2.x && my == box2.y) ||
                          (mx == box3.x && my == box3.y)) &&
                        Map[mx][my] != '#') {
                        state ne = { { { nx, ny }, box1 }, { { mx, my }, box3 } };
                        if (!st[nx][ny][box1.x][box1.y][mx][my][box3.x][box3.y]) {
                            st[nx][ny][box1.x][box1.y][mx][my][box3.x][box3.y] =
                                st[p.x][p.y][box1.x][box1.y][box2.x][box2.y][box3.x][box3.y] + 1;
                            q.push(ne);
                        }
                    }
                } else if (nx == box3.x && ny == box3.y) {
                    int mx = nx + dx[i], my = ny + dy[i];
                    if (1 <= mx && mx <= n && 1 <= my && my <= m &&
                        !((mx == box1.x && my == box1.y) || (mx == box2.x && my == box2.y) ||
                          (mx == box3.x && my == box3.y)) &&
                        Map[mx][my] != '#') {
                        state ne = { { { nx, ny }, box1 }, { box2, { mx, my } } };
                        if (!st[nx][ny][box1.x][box1.y][box2.x][box2.y][mx][my]) {
                            st[nx][ny][box1.x][box1.y][box2.x][box2.y][mx][my] =
                                st[p.x][p.y][box1.x][box1.y][box2.x][box2.y][box3.x][box3.y] + 1;
                            q.push(ne);
                        }
                    }
                } else {
                    state ne = { { { nx, ny }, box1 }, { box2, box3 } };
                    if (!st[nx][ny][box1.x][box1.y][box2.x][box2.y][box3.x][box3.y]) {
                        st[nx][ny][box1.x][box1.y][box2.x][box2.y][box3.x][box3.y] =
                            st[p.x][p.y][box1.x][box1.y][box2.x][box2.y][box3.x][box3.y] + 1;
                        q.push(ne);
                    }
                }
            }
        }
    }
    return -1;
}
int main() {
    PII p;
    vector<PII> box;
    scanf("%d%d", &n, &m);
    for (int i = 1; i <= n; i++) {
        scanf("%s", Map[i] + 1);
        for (int j = 1; j <= m; j++) {
            if (Map[i][j] == 'X')
                p = { i, j };
            if (Map[i][j] == '*')
                box.push_back({ i, j });
        }
    }
    printf("%d", bfs(p, box[0], box[1], box[2]));
    return 0;
}

T6

现在有两个字符串A和B,它们都是由小写字母组成。你现在有一把神奇的字符串刷子,每次可以刷一个区间,刷完之后,这个区间的字母都变成一个你想要的字母。现在你的任务是通过字符刷子,把字符串A变成字符串B。最少需要刷多少次呢?

首先还是%一下CQR与CZY,这两位在赛场上就打出的DALAO。
果然,悲伤的DP,悲伤的我。
首先先提供一个假做法(45pts):每一次使整个排列与左端点相同,然后分段进行次过程。
然后考虑正解DP。
考虑f[l][r][color]表示在[l,r]的区间,将其染成color所需的步数。
然后就可以愉快的进行记忆化搜索了。

#include &lt;bits/stdc++.h&gt;
using namespace std;
const int N = 105;
char A[N], B[N];
int a[N], b[N], f[N][N][30];
int dfs(int l, int r, int color) {
    if (l &gt; r)
        return 0;
    if (l == r) {
        if (!color)
            return a[l] != b[l];
        else
            return b[l] != color;
    }
    int &amp;u = f[l][r][color];
    if (~u)
        return u;
    u = 1e9;
    if (!color) {
        if (a[l] == b[l])
            u = dfs(l + 1, r, color);
        else {
            for (int i = l; i &lt;= r; i++) {
                if (b[i] == b[l])
                    u = min(u, dfs(l, i, b[l]) + dfs(i + 1, r, color) + 1);
            }
        }
    } else {
        if (color == b[l])
            u = dfs(l + 1, r, color);
        else {
            for (int i = l; i &lt;= r; i++) {
                if (b[i] == b[l])
                    u = min(u, dfs(l, i, b[l]) + dfs(i + 1, r, color) + 1);
            }
        }
    }
    return u;
}
int main() {
    memset(f, -1, sizeof f);
    scanf(&quot;%s%s&quot;, A + 1, B + 1);
    for (int i = 1; i &lt;= strlen(A + 1); i++) {
        a[i] = A[i] - 'a' + 1;
        b[i] = B[i] - 'a' + 1;
    }
    printf(&quot;%d&quot;, dfs(1, strlen(A + 1), 0));
    return 0;
}
训练日志

文章导航

Previous Post: CZYZ Training Day1 (8.7)
Next Post: 南京day?

发表回复 取消回复

要发表评论,您必须先登录。

2025年 6月
一 二 三 四 五 六 日
 1
2345678
9101112131415
16171819202122
23242526272829
30  
« 2月    

2024常州 Class Classic OI Problems Contest cqr的长乐集训2023 CZYZ LOC New Game NOI NOIP Password Protected PM_PK Preview Problems Retrospect Selfmade Qusetion STL The end Training Uneasy Problem 蒟蒻 通报

  • 训练日志
  • 链表
  • 入门
  • 模拟
  • dfs序
  • 并查集
  • spfa
  • 最小割
  • 矩阵树定理
  • 仙人掌
  • BSGS
  • 凸包
  • 回文自动机
  • 递推与动归
  • 堆
  • 莫队算法
  • ST表
  • Treap
  • 树套树
  • 可持久化线段树
  • 初赛
  • 搜索
  • 贪心
  • 深度优先搜索
  • 欧拉图
  • dijkstra
  • 费用流
  • 哈夫曼树
  • kruskual
  • 置换
  • 旋转卡壳
  • KMP
  • 区间动归
  • STL
  • 链表
  • 可并堆
  • sply
  • 主席树
  • 可持久化字典树
  • 算法
  • 动态规划
  • 构造
  • 广度优先搜索
  • 最短路
  • floyd
  • 最大流
  • 虚树
  • prim
  • 筛法
  • 半平面交
  • 字典树
  • 背包动归
  • 基础数据结构
  • 分块
  • 线段树
  • 替罪羊树
  • K-DTree
  • 图论
  • 二分法
  • 迭代搜索
  • 拓扑排序
  • 有上下界网络流
  • 生成树
  • 快速幂
  • 后缀数组
  • 树形动归
  • 哈希表
  • 中级数据结构
  • 平衡树
  • 可持久化数据结构
  • 数据结构
  • 三分法
  • 启发式搜索
  • 图的连通
  • 点分治
  • 博弈论
  • AC自动机
  • 状压动归
  • 单调栈
  • 树状数组
  • 高级数据结构
  • OI资料
  • 数学
  • 高精度
  • 差分约束
  • 树上倍增
  • 素数测试
  • 后缀自动机
  • 数位动归
  • 单调队列
  • 新闻
  • 几何
  • 随机化
  • 二分图染色
  • 树链剖分
  • 欧拉函数
  • manacher
  • 斜率优化
  • 离线处理
  • 信息学奥赛学长风采
  • 字符串
  • 二分图匹配
  • prufer编码
  • 卡特兰数
  • 密码学
  • 决策单调
  • 赛后总结
  • 其他
  • 2-SAT
  • 最近公共祖先
  • 矩阵乘法
  • 记忆化搜索
  • 网络流
  • Link cut tree
  • 排列组合
  • 树
  • 高斯消元
  • 乘法逆元
  • 容斥原理
  • 调和级数
  • 概率与期望
  • 模线性方程组
  • 莫比乌斯反演
  • 快速傅里叶变换
  • 扩展欧几里德
  • 最大公约数与最小公倍数

近期文章

  • DP杂题
  • 2025年2月13日模拟赛
  • HLOJ-TEST ROUND 4-T1/T2(构造)- 3
  • HLOJ-TEST ROUND 4-T1/T2(构造)- 2
  • HLOJ-TEST ROUND 4-T1/T2(构造)- 1

近期评论

归档

  • 2025年2月
  • 2025年1月
  • 2024年11月
  • 2024年10月
  • 2024年9月
  • 2024年8月
  • 2024年7月
  • 2024年3月
  • 2024年2月
  • 2024年1月
  • 2023年12月
  • 2023年11月
  • 2023年10月
  • 2023年9月
  • 2023年8月
  • 2023年7月
  • 2023年3月
  • 2023年2月
  • 2023年1月
  • 2022年12月

Copyright © 2025 泉州一中信息学Blog.

Powered by PressBook WordPress theme