首页 > 其他分享 >题解:2024牛客多校赛第二场 A Floor Tiles(思维)

题解:2024牛客多校赛第二场 A Floor Tiles(思维)

时间:2024-07-18 22:41:54浏览次数:11  
标签:std Tiles && Floor int 题解 sum 曲线 str

2024 Nowcoder Multi-University Training Contest 2

Problem A. Floor Tiles

题目大意

给你两种正方形图案,分别为以下两种:

1

再给你三个整数 \(N,M,K\) ,表示你需要用这两种图案,拼成一个 \(N\) 列 \(M\) 行的矩形。
由于这两种图案十分特殊,他们能无缝衔接在一起。因此你需要让这个矩形内含有 \(K\) 条不相连的曲线。
比如:图一内有 \(4\) 条曲线,图二内有 \(5\) 条曲线

curve

题目还会给你两个整数 \(x、y\) 和一个字母 \(t\) ,表示在这个矩形内的的第 \(x\) 列第 \(y\) 行必须是输入的字母 \(t\)
如果这种情况可以成立,那么输出 YES 并在下一行开始输出符合上述规则的图形之一;
如果这种情况不能成立,那么输出 NO

我们小组的思路

首先,我们发现:

  • 一个 \(N\) 列 \(M\) 行的矩形内,如果曲线条数最少,那么肯定有一种情况是全部图案统一(要么全部为 \(A\) ,要么全部为 \(B\) ),且这个数量为 \(N + M\)
  • 在上条发现的基础上,增添一种 \(2 * 2\) 的结构可以形成一个圆形,同时增加一条曲线:
AB
BA
  • 再在上一条发现的基础上,一个 \(N * M\) 的矩形内最多有 \(( N - 1 ) * ( M - 1 ) / 2\) 个圆。特殊的,如果边长均为偶数同时左上角的图案必须为 A 的话 还能再多一个 (虽然后面我们发现并没有什么用但是课可以帮助我们能理解这种图形)
  • 如果某个地方的图案不能(或者说不需要)改变的话——这种情况就是第二条中的结构中:假设全部为 \(A\) 的情况下增加 \(B\) ,那么 \(A\) 就是不需要改变的(反之假设全部为 \(B\) 的情况下增加 \(A\) ,那么 \(B\) 就是不需要改变的),那么这个图案沿着45°斜线去移动能到达的所有位置都不会改变
举个例子
ABABABAB
BABABABA
ABABABAB
BABABABA
这个矩形里所有的A都是不改变的(因为一旦变了,曲线数量就会减少)
同样的,B也是如此

其次,我们设计程序

  1. 先输入 \(n , m , k , x , y , t\),然后计算出 min(曲线最少情况)
  2. 第一,判断只有一行或者一列的时候能不能行,因为这种情况下是不能形成圆形区域的,所以曲线数量一定为 \(N + M\) 。(特判1)
  3. 第二,判断 \(k\) 是否小于最小值。(特判2)
  4. 沿着斜线,把不动点平移到左上角,使他到达 \(( 0 , 1 )\) 或者 \(( 1 , 0 )\) ,这样就能确定哪些位置是需要改变的了(因为要改变才能增加曲线数量)、
  5. 初始化字符串矩阵(假设全部都是不动点的那个字母)和曲线数量 \(( N + M )\)
  6. 每一行去遍历寻找哪些点是可以改变的(详情参考上面的例子),在改变的同时检测是否出现了能形成圆形的结构,更新曲线数量
  7. 当曲线数量到达目标数量时,可以输出 YES 和字符串矩阵;
  8. 如果整个矩阵遍历完,还达不到目标数量的话,就输出 NO

我们的代码

#include <bits/stdc++.h>
#define int long long

const int N = 805;
int T;
int n,m,k,x,y;
std::string s_t;
char t,c_t;
int min,max,add,sum;
std::string str[N];

void solve() {
    std::cin >> n >> m >> k;
    min = n + m;

    std::cin >> x >> y >> s_t;
    t = s_t[0];
    c_t = (t == 'A' ? 'B' : 'A');

    if (n == 1 || m == 1) {
        if (k != n + m) std::cout << "NO\n";
        else {
            std::cout << "YES\n";
            for (int i = 1; i <= n; i++) {
                for (int j = 1; j <= m; j++) {
                    std::cout << t;
                }
                std::cout << "\n";
            }
        }
        return;
    }   //特判边长为1

    if (min > k) {
        std::cout << "NO\n";
        return;
    }   //判断是否落在范围之内

    int umi = std::min(x, y);
    x -= umi;
    y -= umi;
    x &= 1;
    y &= 1;
    if (x > y) std::swap(x, y);
    //等效转移不动点

    int u = 1 - y;
    //确定哪个位置加A或者B

    add = k - min;
    for (int i = 0; i < n; i++) {
        str[i].resize(m);
        for (int j = 0; j < m; j++) {
            str[i][j] = t;
        }
    }
    //初始化,假设全部为t时,曲线数量最少
    
    sum = min;
    for (int i = 0 ; i < n && sum < k; i ++) {
        for(int j = u; j < m && sum < k; j += 2) {
            str[i][j] = c_t;

            if (c_t == 'A' && i >= 1 && j >= 1 && str[i - 1][j - 1] == 'A' && str[i - 1][j] == 'B' && str[i][j - 1] == 'B') sum++;
            else if (c_t == 'B' && i >= 1 && j < m-1 && str[i - 1][j] == 'A' && str[i - 1][j + 1] == 'B' && str[i][j + 1] == 'A') sum++;
        }
        u = 1 - u;
    }

    if(sum != k) std::cout << "NO\n";
    else {
        std::cout << "YES\n";
        for (int z = 0; z < n; z++) std::cout << str[z] << "\n";
    }

}

signed main()
{
    std::ios::sync_with_stdio(false);
    std::cin.tie(nullptr);
    std::cout.tie(nullptr);

    T = 1;
    std::cin >> T;
    while (T--) solve();
    return 0;
}

标签:std,Tiles,&&,Floor,int,题解,sum,曲线,str
From: https://www.cnblogs.com/jiejiejiang2004/p/18310541

相关文章

  • GESP编程能力等级认证C++编程真题解析 | 2024年3月五级
    学习C++从娃娃抓起!记录下CCF-GESP备考学习过程中的题目,记录每一个瞬间。附上汇总贴:GESP编程能力等级认证C++编程真题解析|汇总单选题第1题唯一分解定理描述的内容是()?A.任意整数都可以分解为素数的乘积B.每个合数都可以唯一分解为一系列素数的乘积C.两个不同的......
  • 题解:CF1912D Divisibility Test
    又是一道水绿。刚刚小学毕业的数学idiot——我释怀地笑了。第一种很好判断,当$b^k$为$n$的倍数时,取基数为$b$的能被$n$整除的整数$c$的最后$k$位数显然能被$n$整除。第二种也不难,当$b^k\equiv1\pmodn$时,取以$b$为底数的能被$n$整除的整数$c$的$k$......
  • Load balancer does not contain an instance for the service service-B [503] duri
    场景:service-A服务通过openFeign远程调用service-B服务的test()方法,结果报错Loadbalancerdoesnotcontainaninstancefortheserviceservice-Bfeign.FeignException$ServiceUnavailable:[503]during[POST]to[http://service-B/test]原因:报错信息的意思......
  • [题解]P1896互不侵犯
    数位DP模板题link题面[SCOI2005]互不侵犯题目描述在\(N\timesN\)的棋盘里面放\(K\)个国王,使他们互不攻击,共有多少种摆放方案。国王能攻击到它上下左右,以及左上左下右上右下八个方向上附近的各一个格子,共\(8\)个格子。输入格式只有一行,包含两个数\(N,K\)。输出格......
  • T3 飞刀传承 题解
    题目描述李家自古以来就是飞刀名门,每一任家主都唤作小李。这一代的小李更是青出于蓝,将祖传的飞刀绝技使得出神入化,年纪轻轻便继承了李家祖传的招式,担下了家主之位。不料有日凶兽来袭,李家满门几尽被灭,只剩少数流落在外的弟子得以幸存。他一度想要自尽,却因李家飞刀绝技不能在他手上......
  • T2 替换字母2 题解
    题目描述:有长度为\(n\)的字符串,仅包含小写字母。小信想把字符串变成只包含一种字母。他每次可以选择一种字符\(c\),然后把长度最多为\(m\)的子串中的字符都替换成\(c\)。小信想知道最少需要操作几次能让字符串只包含一种字母。题意简述给定一个长度为\(n\)的小写字母串,每次可以......
  • T1 此方的身高排序 题解
    题目描述:体育馆里有\(n\)个人正在排队等待着上体育课,他们每个人都不一样高。此方想要把队伍从小个子到高个子进行排序,即让队伍身高为升序。此方每次调出一人,让此人和在他后面的人比身高,如果比对方高,则两人交换位置并和下一个人继续比较,直到比对方矮或者已经在队尾。现在给出......
  • CF208E 题解
    BloodCousins前置知识:线段树合并。我们先把题目转化一下。这里先设\(v\)的\(p\)级祖先为\(u\),事实上要求的东西就是\(u\)的\(p\)级后代的个数减\(1\),减\(1\)是因为要把自己减去。显然这个目标点\(t\)要满足两个要求:\(t\)在\(u\)子树内。设\(dep_u\)表......
  • P3242 接水果 题解
    Statement树,给\(m\)条带权路径\((a,b,v)\),\(q\)次询问包含\((u,v)\)的路径中的第\(k\)小权值.Solution好题!这篇题解延伸出了很多东西。首先路径的包含关系转为矩形(二维限制关系)是比较显然的.具体地,\((u,v)\)包含\((a,b)\)有两种情况:\(u,v\)无祖先关系:\(a\)在......
  • P1912 [NOI2009] 诗人小G 题解
    我们设\(s_i\)表示前\(i\)个句子的长度之和,这样就有dp\[f_i=\min_{j<i}\big\{f_j+|s_i-s_j+i-j-1-L|^P\big\}\]我们设\(w(l,r)=|s_r-s_l+r-l-1-L|^P\),如果\(w\)满足四边形不等式,则原dp具有决策单调性。设\(u=(s_i+i)-(s_j+......