首页 > 其他分享 >[ABC326D] ABC Puzzle 题解

[ABC326D] ABC Puzzle 题解

时间:2023-11-18 21:25:47浏览次数:40  
标签:ABC return int 题解 Puzzle ++ const SE define

题目链接

解法分析

这个问题是一个经典的排列谜题,通过回溯算法来穷举所有可能的字符排列,然后验证是否满足行和列约束。这个解决方案可以用于解决类似的谜题,其中需要满足一定的排列条件。通过仔细考虑约束条件,可以加快解决问题的速度,减少不必要的计算。

更详细的我写在代码里了。

代码

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

// chmax和chmin是模板函数,用于在满足条件时更新值。
template<class T> bool chmax(T &a, const T &b) { if (a < b) { a = b; return true; } return false; }
template<class T> bool chmin(T &a, const T &b) { if (b < a) { a = b; return true; } return false; }

// 定义一些宏和常量
#define all(x) (x).begin(),(x).end()
#define fi first
#define se second
#define mp make_pair
#define si(x) int(x.size())
const int mod = 998244353, MAX = 300005, INF = 1 << 30;

char S[6][6]; // 一个二维字符数组,用于存储网格的当前状态
string R, C; // 字符串R和C表示行和列的约束
int N; // 网格的大小(N x N)

// “solve”函数是一个递归函数,用于尝试解决这个谜题。
void solve(int u) {
    if (u == N) { // 如果我们已经填满了所有行,检查解是否有效。
        // 检查行约束是否满足。
        for (int i = 0; i < N; i++) {
            for (int j = 0; j < N; j++) {
                if (S[i][j] != '.') {
                    if (R[i] != S[i][j]) return; // 如果行中的字符与约束不匹配,返回。
                    break;
                }
            }
        }
        
        // 检查列约束是否满足。
        for (int j = 0; j < N; j++) {
            set<char> SE;
            for (int i = 0; i < N; i++) {
                if (S[i][j] == '.') continue;
                if (SE.count(S[i][j])) return; // 如果列中有字符重复,返回。
                SE.insert(S[i][j]);
            }
            if (si(SE) <= 2) return; // 如果列中有超过2个字符,返回。
            for (int i = 0; i < N; i++) {
                if (S[i][j] == '.') continue;
                if (C[j] != S[i][j]) return; // 如果列中的字符与约束不匹配,返回。
                break;
            }
        }
        
        // 如果所有约束都满足,打印解并退出。
        cout << "Yes\n";
        for (int i = 0; i < N; i++) {
            for (int j = 0; j < N; j++) cout << S[i][j];
            cout << "\n";
        }
        exit(0);
    }
    
    // 尝试当前行的所有可能字符组合。
    for (int a = 0; a < N; a++) {
        for (int b = 0; b < N; b++) {
            if (a == b) continue;
            for (int c = 0; c < N; c++) {
                if (a == c || b == c) continue;
                
                // 检查当前组合是否满足当前行的约束。
                if (R[u] == 'A') {
                    if (!(a < b && a < c)) continue;
                }
                if (R[u] == 'B') {
                    if (!(b < a && b < c)) continue;
                }
                if (R[u] == 'C') {
                    if (!(c < a && c < b)) continue;
                }
                // 填充当前行的字符。
                S[u][a] = 'A';
                S[u][b] = 'B';
                S[u][c] = 'C';
                // 递归尝试解决下一行。
                solve(u + 1);
                // 重置字符以进行回溯。
                S[u][a] = '.';
                S[u][b] = '.';
                S[u][c] = '.';
            }
        }
    }
}

int main() {
    cin.tie(0);
    ios::sync_with_stdio(false);
    
    cin >> N >> R >> C; // 读取网格大小和行/列约束。
    for (int i = 0; i < N; i++)
        for (int j = 0; j < N; j++)
            S[i][j] = '.'; // 用空单元格初始化网格。
    solve(0); // 从第一行开始解决谜题。
    cout << "No\n"; // 如果找不到解,打印"No"。
}

标签:ABC,return,int,题解,Puzzle,++,const,SE,define
From: https://www.cnblogs.com/IOIAKmerlin/p/17832500.html

相关文章

  • P2678 跳石头 题解
    P2678跳石头链接这道题其实很水我们二分最长距离,最后用$check$函数判断合不合法一下是核心代码$check$函数这样写:boolcheck(intx){ intlast=0,tot=0; for(inti=1;i<=n;i++){ if(a[i]-last<x)tot++; elselast=a[i]; } if(len-last<x)tot++; returntot<......
  • CF1552D题解
    CF1552D题解思路首先,$a_i$的正负不重要,如果$a_i=b_j-b_k$,那么就有$-a_i=b_k-b_j$,读入时将$a_i$全部转化为正数。若满足$a_i+a_j+\ldots+a_k$,那么就可以构造出$b$序列,否则不行。从左到右遍历一遍$a$序列,动态规划推出所有可以组成的和,并判断是否满足上式,时间复杂度$O......
  • CF985C 题解
    CF985C题解思路由题意得知,现在有$n\timesk$块木板需要组装成$n$个木桶,每个木桶由$k$块板组成,容量服从短板原理,要求容量差不得超过$I$,求最大容量和。不管采用什么方法,无疑我们首先需要将板长(数组$a$)从小到大排列。利用贪心算法。先找出与$a_0$的长度差不超过$l$的......
  • AtCoder Beginner Contest(abc) 296
    B-Chessboard难度:⭐题目大意给定一个8*8的字符矩阵,其中只有一个'*',输出它的坐标;其坐标的列用字母表示,行用数字表示,具体看样例解释;解题思路签到题不多嗦了;神秘代码#include<bits/stdc++.h>#defineintlonglong#defineIOSios::sync_with_stdio......
  • UVA10652 Board Wrapping 题解
    LinkUVA10652BoardWrappingQuestion给出\(N\)个矩形,求面积最小的凸多边形能包住所有矩形求矩形面积占凸多边形面积的百分比Solution把矩形的四个顶点拿出来,就可以转化成凸包裸题了Code#include<bits/stdc++.h>usingnamespacestd;constdoubleeps=1e-9;constd......
  • NEFU OJ Problem1487 时空乱流题解
    时空乱流Problem:ETimeLimit:1500msMemoryLimit:65535KDescription星际飞行员Alice在一次航行中遭遇了时空乱流,时空乱流将导致Alice乘坐的飞船在n个位面之间穿梭。星际宇航局管理员Bob收到了Alice的求救信号,决定在某些位面上设立监测站,当Alice进入某个已经设立监......
  • 关于maven构建tomcat服务器一直启动不了的问题解决
    以往我都是创建maven项目后自己去配置web,再通过自己配置以下信息之后,配置tomcat。最终结果是始终报错 之后摸索发现,可以在maven项目配置前将以上“maven主路径,用户设置文件,本地仓库”信息确定好。 在弹出的页面设置好后,再创建maven项目便省时很多,tomcat配置后可以使用 ......
  • 【HDU 1276】士兵队列训练问题 题解(链表+模拟)
    某部队进行新兵队列训练,将新兵从一开始按顺序依次编号,并排成一行横队,训练的规则如下:从头开始一至二报数,凡报到二的出列,剩下的向小序号方向靠拢,再从头开始进行一至三报数,凡报到三的出列,剩下的向小序号方向靠拢,继续从头开始进行一至二报数。。。,以后从头开始轮流进行一至二报数、一至......
  • T399753 counting problem(计数问题)题解
    LinkT399753countingproblem(计数问题)Question给出一个正整数\(n\),求\(AB+CD=n\)的方案数,\(A,B,C,D\)都是要求是正整数Solution考虑直接枚举\(ABCD\)显然是不切实际的那么就折半枚举设\(F_i\)表示两个数的乘积为\(i\)的方案数答案就是\(\sum\limits_{i=1......
  • T399750 Cell kingdom(Hard) 题解
    LinkT399750Cellkingdom(Hard)Qustion第一天产生\(1\)个细胞,之后的每一天,一个细胞都会分裂成\(8\)个和自己一样的细胞,每个细胞在第三天都会自爆并且带走当天产生的\(6\)个细胞,求第\(x\)天有多少细胞Solution我们设\(F[i]\)表示第\(i\)天产生的新细胞个数那么可......