首页 > 其他分享 >CF 1863D 题解

CF 1863D 题解

时间:2023-09-02 11:55:36浏览次数:58  
标签:1863D 格子 int 题解 CF else cnt3 骨牌 ans

CF1863D Two-Colored Dominoes 题解

洛谷

Codeforces

Description

有一个 \(n \times m\) 的棋盘,上面铺着一些 \(1 \times 2\) 的多米诺骨牌(横竖均有可能),骨牌之间没有重叠。

你需要找到一种染色方案满足以下条件:

  • 每个多米诺骨牌一端被染白,另一端被染黑。其他没有骨牌的格子不染色。
  • 对于棋盘的每一行,被染黑的格子数等于被染白的格子数。
  • 对于棋盘的每一列,被染黑的格子数等于被染白的格子数。

请输出任意一种染色方案,如果无解,输出 \(-1\)。

本题有多组测试数据,\(1 \leq T \leq 10^{4}\),\(2 \leq n,m \leq 500\),\(\sum (n \times m) \leq 2.5 \times 10^{5}\)。

Solution

由于题目限制每个多米诺骨牌一端被染白,另一端被染黑,因此容易得出 横着摆放的骨牌对行的限制没有影响,横着摆放的骨牌对列的限制没有影响。

因此我们可以先看行的限制,显然,如果一行中有奇数个竖着放的骨牌则无解。

然后分类讨论:

  • 若当前格子是骨牌的上侧,没有限制,但要考虑后面的格子。
  • 若当前格子是骨牌的下侧,由于上一行已经遍历过,当前格子的状态就已经确定了。

因此我们可以记录三个数字,\(cnt_{1}\) 表示没有限制的格子数量,\(cnt_{2}\) 表示一定需要染黑的数量,\(cnt_{3}\) 表示一定需要染白的数量。

统计结束后,对于每个没有限制的格子,我们贪心的选择当前少的颜色涂,数量相同的时候随便选一个就行,这样到最后如果两个颜色数量还不同就无解了。

列的限制同理即可。

时间复杂度 \(\Omicron \left( n \times m\right)\)。

Codes

#include <bits/stdc++.h>
using namespace std;
#define int long long
void read(int &p)
{
    p = 0;
    int k = 1;
    char c = getchar();
    while (c < '0' || c > '9')
    {
        if (c == '-')
        {
            k = -1;
        }
        c = getchar();
    }
    while (c >= '0' && c <= '9')
    {
        p = p * 10 + c - '0';
        c = getchar();
    }
    p *= k;
    return;
}
void write_(int x)
{
    if (x < 0)
    {
        putchar('-');
        x = -x;
    }
    if (x > 9)
    {
        write_(x / 10);
    }
    putchar(x % 10 + '0');
}
void writesp(int x)
{
    write_(x);
    putchar(' ');
}
void writeln(int x)
{
    write_(x);
    putchar('\n');
}
int T;
int n,m;
char mp[510][510],ans[510][510];
void solution()
{
    read(n),read(m);
    for(int i = 1;i <= n;i++)
    {
        for(int j = 1;j <= m;j++)
        {
            ans[i][j] = '.';
        }
    }
    for(int i = 1;i <= n;i++)
    {
        scanf("%s",mp[i] + 1);
    }
    // 是否有答案;
    bool flag = true;
    // 先考虑行的情况,由于横着的不会造成影响直接跳过
    for(int i = 1,cnt1,cnt2,cnt3;i <= n;i++)
    {
        // cnt1 无法确定个数
        // cnt2 确定的 B
        // cnt3 确定的 W
        cnt1 = cnt2 = cnt3 = 0;
        for(int j = 1;j <= m;j++)
        {
            if(mp[i][j] == 'U')
            {
                ++cnt1;
            }
            else if(mp[i][j] == 'D')
            {
                if(ans[i - 1][j] == 'W')
                {
                    ++cnt2;
                }
                else
                {
                    ++cnt3;
                }
            }
        }
        if((cnt1 + cnt2 + cnt3) & 1)
        {
            flag = false;
            break;
        }
        else
        {
            for(int j = 1;j <= m;j++)
            {
                if(mp[i][j] == 'U')
                {
                    if(cnt2 > cnt3)
                    {
                        ans[i][j] = 'W';
                        ++cnt3;
                    }
                    else
                    {
                        ans[i][j] = 'B';
                        ++cnt2;
                    }
                }
                else if(mp[i][j] == 'D')
                {
                    if(ans[i - 1][j] == 'W')
                    {
                        ans[i][j] = 'B';
                    }
                    else
                    {
                        ans[i][j] = 'W';
                    }
                }
            }
        }
        if(cnt2 != cnt3) {
            flag = false;
        }
    }

    for(int j = 1,cnt1,cnt2,cnt3;j <= m;j++) {
        cnt1 = cnt2 = cnt3 = 0;
        for(int i = 1;i <= n;i++) {
            if(mp[i][j] == 'L') {
                ++cnt1;
            }
            else if(mp[i][j] == 'R') {
                if(ans[i][j - 1] == 'W') {
                    ++cnt2;
                }
                else {
                    ++cnt3;
                }
            }
        }
        if((cnt1 + cnt2 + cnt3) & 1) {
            flag = false;
            break;
        }
        else {
            for(int i = 1;i <= n;i++) {
                if(mp[i][j] == 'L') {
                    if(cnt2 > cnt3) {
                        ans[i][j] = 'W';
                        ++cnt3;
                    }
                    else {
                        ans[i][j] = 'B';
                        ++cnt2;
                    }
                }
                else if(mp[i][j] == 'R') {
                    if(ans[i][j - 1] == 'W'){
                        ans[i][j] = 'B';
                    }
                    else{
                        ans[i][j] = 'W';
                    }
                }
            }
        }
        if(cnt2 != cnt3){
            flag = false;
        }
    }
    if(flag == false){
        puts("-1");
        return ;
    }
    for(int i = 1;i <= n;i++){
        for(int j = 1;j <= m;j++){
            putchar(ans[i][j]);
            ans[i][j] = '.';
        }
        puts("");
    }
}
signed main()
{
    read(T);
    while(T--){solution();}
    return 0;
}

标签:1863D,格子,int,题解,CF,else,cnt3,骨牌,ans
From: https://www.cnblogs.com/yuhang-ren/p/17673505.html

相关文章

  • 题解 [AGC004D] Teleporter
    题目链接躺在床上想到重要性质的题目。。。首先,由于每个城市只有一个可以直接到达的城市,所以\(n\)个城市就有\(n\)条边,容易发现这是一棵基环树,那么我们先从普通树的角度考虑,若要求每个点走\(k\)条边恰好到\(1\)号节点,这个环必须加在哪里。若\(k=1\),没有环显然也是可行......
  • GCD Counting题解
    题意有一棵有\(n\)个节点的树,第\(i\)个节点有点权\(a_i\)。定义\(g(x,y)\)为\(x\)到\(y\)的树上路径所经过的点的点权\(\gcd\)。对于每一个正整数\(k\in[1,2\times10^5]\)求出满足以下条件的\(x,y\)的对数:\(1\lex\ley\len\)\(g(x,y)=k\)\(1\len......
  • CF915G Coprime Arrays 题解
    题意给定\(n,k\),对于所有的\(m\in\left[1,k\right]\),求长度为\(n\),值域为\(\left[1,m\right]\)且最大公约数为\(1\)的序列种数,对\(10^9+7\)取模。(\(1\len,k\le2\times10^6\))。题解设\(f(d,m)\)表示长度为\(n\),值域为\(\left[1,m\right]\)且最大......
  • [NOI2021] 轻重边题解
    题目传送门一眼数据结构考虑树上有什么数据结构支持\(x\)到\(y\)节点的修改和查询,那就是:树链剖分。那么这道树链剖分的题有个\(trick\):边点转换&染色法,对于每次修改,考虑将修改路径上的点全部染上一种独一无二的颜色,而查询的时候,就查询路径上相邻的相同的颜色节点个数即可......
  • 《CF1863》 解题报告
    题面传送器首先有一个\(naive\)的做法。直接\(O(n^3)\)暴力判断。考虑寻找突破口。假如给了你一个序列,异或值为\(S\),那么实际上假如中间有一个断点\(mid\),那么我们最终决定保留哪一段,实际上是看\(S\)的最高位\(1\)的位置来比较的,所以我们只需要管最高位的\(1\)......
  • 爱思创模拟06试题易错题解析
    错误原因:漏项正确答案:C按节点数分类穷举 举一反三:  错误原因:处理三个空位的时候,情况考虑的太多正确答案:分情况计算,先枚举4个人共A(4,4)=24种情况,再考虑剩下两个空位置的情况,即A(5,2)=20种情况,最终答案就是24*20=480种举一反三:  错误原因:不会计算时间复杂度......
  • (持续更新)CF赛后失误总结
    在CF上比赛中反映出的问题总结目录在CF上比赛中反映出的问题总结总是存在的问题:EducationalCodeforcesRound154(8.31)结果(+164)总结:PinelyRound2(8.30)结果:(+231)总结:(找性质)更早以前:总是存在的问题:总想把前面的做对,浪费了宝贵的时间AC后面的EducationalCodeforcesRound......
  • 题解 正妹吃月饼
    题目链接由于每个质量的月饼只有一个,并且质量恰好是2的整数倍,所以考虑将一个质量看成一个二进制位。那么也就是说,我们要构造一个二进制数\(x\),使得\(x\)的\(1\)的个数最多,且满足\(a\lex\leb\)。那么这就可以用类似数位\(DP\)的思路来做,从高位往低位看,若\(a_i=b_i=1......
  • NOIP2012提高组初赛易错题解析
    一.3. 错误原因:忘记了解析:Intel是全球最大的CPU厂商,AMD是世界上首个研发出7纳米CPU的厂商 6.错误原因:忘记了解析:ENIAC是世界上首台计算机,属于第一代计算机,即电子管计算机 10.错误原因:选项理解错误解析:A由蝙蝠,发明雷达是正确的,B因特网的发明与蜘蛛网无关,只是形......
  • NOIP2011提高组初赛易错题解析
    一.7.错误原因:不知道解析:快速排序在理论上最低的时间复杂度为O(n),但实际最低的时间复杂度为O(nlogn) 二.1.错误原因:漏项了解析:这棵树最少有12层,但题目是问可能是几层,所以还可能是2011层 5.错误原因:漏了一种情况解析:这道题的树有两种,所以答案也有两种 ......