首页 > 其他分享 >【ABC322D】题解

【ABC322D】题解

时间:2023-10-09 22:25:14浏览次数:29  
标签:index return int 题解 矩阵 旋转 ABC322D

AtCoder Beginner Contest 322 Problem D - Polyomino 题解

Meaning - 题意简述

给定三个字符矩阵,求它们能不能拼在一起变成一个 \(4 \times 4\) 的全部是 # 的矩阵。

Solution - 题解思路

大模拟。说简单也不简单,很复杂;但是说难呢,又不难。

思路:搜索每一个矩阵的状态。

0x001 旋转矩阵

一个字符矩阵,考虑顺时针旋转 \(90\) 度,推出来得到:

\[t_{i,j} = s_{4 - j + 1,i} \]

所以得到了代码:

// 旋转矩阵
void swp(int index){
  for (int i = 1; i <= 4; i++){
    for (int j = 1; j <= 4; j++){
      sp[index][4 - j + 1][i] = s[i][j];
    }
  }
}

0x002 平移矩阵

枚举偏移量,然后暴力判断是否可以偏移。

代码:

// 平移矩阵
bool py(int index,int x,int y){
  for (int i = 1; i <= 4; i++){
    for (int j = 1; j <= 4; j++){
      if (sp[index][i][j] == '#' && (x + i > 4 || y > j > 4 || x + i < 1 || y + j < 1)){
        return false;
      }
    }
  }
  return true;
}
    

弄完上面两个东西之后,就可以开始暴力 dfs,枚举旋转次数和偏移量,存起来,判断是否合法即可。

0x003 Accept Code - 代码

Accept Record

#include <bits/stdc++.h>

using namespace std;

char s[4][5][5], sp[4][5][5], pt[4][5][5], t[5][5];
int vis[5][5], t1[4], t2[4];

// 旋转矩阵
void swp(int index) {
  for (int i = 1; i <= 4; i++) {
    for (int j = 1; j <= 4; j++) {
      t[i][j] = sp[index][i][j];
    }
  }
  for (int i = 1; i <= 4; i++) {
    for (int j = 1; j <= 4; j++) {
      sp[index][i][j] = t[4 - j + 1][i];
    }
  }
}

// 平移矩阵
bool py(int index, int x, int y) {
  for (int i = 1; i <= 4; i++) {
    for (int j = 1; j <= 4; j++) {
      if (sp[index][i][j] == '#' &&
          (x + i > 4 || y + j > 4 || x + i < 1 || y + j < 1)) {
        return false;
      }
    }
  }
  return true;
}

// 检查矩阵
bool check() {
  for (int i = 1; i <= 4; i++) {
    for (int j = 1; j <= 4; j++) {
      if (vis[i][j] != 1) {
        return false;
      }
    }
  }
  return true;
}

// 求最后的分布情况
void ok() {
  for (int i = 1; i <= 4; i++) {
    for (int j = 1; j <= 4; j++) {
      vis[i][j] = 0;
    }
  }
  for (int id = 1; id <= 3; id++) {
    for (int x = 1; x <= 4; x++) {
      for (int y = 1; y <= 4; y++) {
        vis[x + t1[id]][y + t2[id]] += pt[id][x][y] == '#';
      }
    }
  }
}

// dfs 搜索
void dfs(int x) {
  if (x > 3) {
    ok();
    if (check()) {
      cout << "Yes";
      exit(0);
    }
    return;
  }
  for (int i = 1; i <= 4; i++) {
    for (int j = 1; j <= 4; j++) {
      sp[x][i][j] = s[x][i][j];
    }
  }
  for (int scnt = 1; scnt <= 4; scnt++) {       // 枚举旋转次数
    for (int pyl1 = -4; pyl1 <= 4; pyl1++) {    // 行偏移量
      for (int pyl2 = -4; pyl2 <= 4; pyl2++) {  // 列偏移量
        if (py(x, pyl1, pyl2)) {
          for (int i = 1; i <= 4; i++) {
            for (int j = 1; j <= 4; j++) {
              pt[x][i][j] = sp[x][i][j];
            }
          }
          t1[x] = pyl1, t2[x] = pyl2;
          dfs(x + 1);
        }
      }
    }
    swp(x);
  }
}

int main() {
  for (int i = 1; i <= 3; i++) {
    for (int j = 1; j <= 4; j++) {
      for (int k = 1; k <= 4; k++) {
        cin >> s[i][j][k];
      }
    }
  }
  dfs(1);
  cout << "No";
  return 0;
}

标签:index,return,int,题解,矩阵,旋转,ABC322D
From: https://www.cnblogs.com/codehyx-blog/p/solution-abc322_d.html

相关文章

  • P1220 关路灯 题解
    Description给定\(n\)个点的位置\(a_i\)和每秒的花费\(b_i\),你的初始位置是\(s\),你删掉一个点的时间为\(0\)秒,走\(1\)个单位长度的时间是\(1\)秒。请你确定一种关灯顺序,使得所有点的最终花费最小(删掉点后这个点不会再花费)。Solution每删掉一个点,有两种选择:继续往前......
  • 汉诺塔(河内塔)题解
    汉诺塔(河内塔)题解我们定义\(T_n\)为根据规则将\(n\)个圆盘从一根柱子移动到另一根柱子的最少移动步数,按照这样的定义,本道题的答案实际上就是\(T_n\)。通过手动模拟,可得到\(T_1=1,T_2=3\)。同时显然有\(T_0=0\),即表示\(0\)个圆盘根本无需做任何移动。接着我们开始考虑......
  • CF1142D Foreigner题解
    CF1142DForeigner题解前言:题目含义真的好难理解呜呜。遇到的dp套dp的第三题,所以深入进行了理解。参考博文:https://www.cnblogs.com/AWhiteWall/p/16479483.html题意简化:先定义了不充分。首先数字$[1,9]$都不充分,注意没有$0$。当这个数字(设为$x$)大于等于$10$时......
  • 题解 CF457F 【An easy problem about trees】
    尝试理解,感谢cz_xuyixuan的题解。算作是很多情况的补充说明。我们不妨先二分答案,将\(\gemid\)的设为\(1\),\(<mid\)的设为\(0\),于是问题转化为了权值均为\(0/1\)的版本。我们称一棵树的大小为其非叶节点数。我们称一棵大小为奇数的树为奇树,大小为偶数的树为偶树。对......
  • 题解 - CF1972E - Divisors and Table
    这题正解是虚树,本解法卡常,仅适合不会虚树的。(例如本人)注意:下文中根节点深度定义为1.第一步:转化问题我们把$g(x,y,z)$拆开,考虑每个质数是哪些点的因子。包含这个质数的点构成一个点集,我们只需求这个点集S的$\sum\limits_{x,y,z\inS}f(x,y,z)$。第二步:对......
  • P4801题解
    解题思路:确实是一道很好的贪心,但由于加上了水这个影响因素,使题目复杂度上升了不少。(考虑的东西多了嘛)输个入。对饼干温度无脑排序。求最小值。求最大值(用双指针做,后面会讲)。解题过程:先输入(这个步骤就不用我讲了)inta[1000005];longlongn,ws;longlongmin......
  • Codeforces Round 902 (Div. 2) (CF1877) B、C、D 题解
    B题目大意你要传话给\(n\)个人,每传一下话需要花费\(p\),当一个人被传话后,他可以最多传给\(a_i\)个人,每次花费\(b_i\)。问把话传给\(n\)个人的最小花费。分析首先传给第一个人只少要\(p\)下来贪心,每次让花费最小、且能够传话的人去传话。考虑建一个堆,堆内的信息是......
  • 题解 尼克的任务
    有一种和题解区完全不同的做法。首先将所有任务按照时间从小到大排序,接着用\(f_i\)表示处理前\(i\)个任务所能得到的最大空闲时间。回顾一下需要满足的条件:再某个有任务的时刻,如果尼克是空闲的,就必须从中选择一个任务做。那么我们对于第\(i\)个任务,枚举上一个做的任务\(j......
  • P7710 [Ynoi2077] stdmxeypz 题解
    P7710[Ynoi2077]stdmxeypz题解我的第一道Ynoi题,体验感不高,调了大半天,最后发现有个地方\(B_1\)写成\(B_2\)了。分析树上问题,明显是要转到树下的,所以DFS序是一定要求的。有关树上距离,所以\(deep\)数组也是一定要求的。所以我们现在把问题转化成了:给你三个序列\(......
  • 「Round C10 B」间隔 题解
    简要题意本题有\(T\)组数据。给定一个由\(n\)个元素构成的正整数数列\(a_1,a_2,a_3...a_{n-1},a_n\)。问至少需要插入多少个整数才能使得\(a\)的各相邻元素之差相等(不能插入在头尾)。\(a\)数列保证是单调不减的。\(1\len\le10^6,0\lea_i\le10^6,1\leT\le1......