CodeForces 778D Parquet Re-laying 构造
题意:
有两个\(n \times m\)的矩阵\(A,B\),都是由\(1 \times 2\)的砖块铺成,代表初始状态和结束状态
有一种操作可以把两个砖块拼成的\(2 \times 2\)的矩形旋转\(90^{\circ}\)

问如何操作才能使初始状态转化为结束状态,无解输出\(-1\)
分析:
不妨假设\(m\)为偶数,否则可以旋转整个矩阵使得矩阵的列数为偶数
先找一个中间过度状态矩阵\(C\),它的每个砖块都是水平方向的
求出\(A \to C\)和\(B \to C\)的操作序列,因为操作是可逆的,所以就得到了\(A \to C \to B\)的操作序列
从第一行开始逐个扫描,遇到一个竖直方向的砖块就将它旋转,这是可能有两种情况:
- 右边的砖块也是竖直方向的,那么可以直接旋转
- 右边砖块是水平的,那么就递归到子问题:将右边的水平砖块先旋转过来,再一起旋转
算法的正确性不会证=_=
#include <cstdio>
#include <algorithm>
#include <vector>
#include <map>
using namespace std;
const int maxn = 60;
typedef pair<int, int> PII;
#define ALL(x) (x).begin(), (x).end()
int n, m, Max;
char s1[maxn][maxn], s2[maxn][maxn];
vector<PII> a, b;
void rotate(char s[][maxn], int x, int y) {
if(s[x][y] == 'U') {
s[x][y] = s[x+1][y] = 'L';
s[x][y+1] = s[x+1][y+1] = 'R';
} else {
s[x][y] = s[x][y+1] = 'U';
s[x+1][y] = s[x+1][y+1] = 'D';
}
}
bool check(char s[][maxn], int x, int y) {
if(s[x][y] == s[x][y+1] && s[x][y] == 'U' && s[x+1][y] == s[x+1][y+1] && s[x+1][y] == 'D') return true;
if(s[x][y] == s[x+1][y] && s[x][y] == 'L' && s[x][y+1] == s[x+1][y+1] && s[x][y+1] == 'R') return true;
return false;
}
bool adjust(char s[][maxn], int x, int y, int flag, vector<PII>& a) {
if(x + 1 >= n || y + 1 >= m) return false;
if(check(s, x, y)) {
rotate(s, x, y);
a.emplace_back(x, y);
return true;
} else {
if(!adjust(s, x+1-flag, y+flag, flag^1, a)) return false;
rotate(s, x, y);
a.emplace_back(x, y);
return true;
}
}
void op(char& c) {
switch(c) {
case 'L': c = 'U'; break;
case 'U': c = 'L'; break;
case 'R': c = 'D'; break;
case 'D': c = 'R'; break;
}
}
void change(char s[][maxn]) {
for(int i = 0; i < n; i++)
for(int j = 0; j < m; j++) op(s[i][j]);
for(int i = 0; i < Max; i++)
for(int j = 0; j < i; j++)
swap(s[i][j], s[j][i]);
}
int main()
{
scanf("%d%d", &n, &m);
for(int i = 0; i < n; i++) scanf("%s", s1[i]);
for(int i = 0; i < n; i++) scanf("%s", s2[i]);
Max = n > m ? n : m;
bool changed = false;
if(m & 1) { change(s1); change(s2); swap(n, m); changed = true; }
for(int i = 0; i < n; i++) {
for(int j = 0; j < m; j += 2) {
if(s1[i][j] != 'L') {
if(!adjust(s1, i, j, 1, a)) { puts("-1"); return 0; }
}
if(s2[i][j] != 'L') {
if(!adjust(s2, i, j, 1, b)) { puts("-1"); return 0; }
}
}
}
reverse(ALL(b));
a.insert(a.end(), ALL(b));
printf("%d\n", (int)a.size());
for(pair<int, int> t : a) {
if(changed) swap(t.first, t.second);
printf("%d %d\n", t.first + 1, t.second + 1);
}
return 0;
}
CodeForces 778D Parquet Re-laying 构造的更多相关文章
- CF 778D Parquet Re-laying——构造
题目:http://codeforces.com/problemset/problem/778/D 完全没思路……就看了题解. 很好地思路是考虑操作可逆,所以起始状态和最终状态都变到一个中转状态,即都 ...
- Educational Codeforces Round 10 B. z-sort 构造
B. z-sort 题目连接: http://www.codeforces.com/contest/652/problem/B Description A student of z-school fo ...
- Codeforces 707C Pythagorean Triples(构造三条边都为整数的直角三角形)
题目链接:http://codeforces.com/contest/707/problem/C 题目大意:给你一条边,问你能否构造一个包含这条边的直角三角形且该直角三角形三条边都为整数,能则输出另外 ...
- Codeforces 1246D/1225F Tree Factory (构造)
题目链接 https://codeforces.com/contest/1246/problem/D 题解 首先考虑答案的下界是\(n-1-dep\) (\(dep\)为树的深度,即任何点到根的最大边 ...
- Codeforces - 1202D - Print a 1337-string... - 构造
https://codeforces.com/contest/1202/problem/D 当时想的构造是中间两个3,然后前后的1和7组合出n,问题就是n假如是有一个比较大的质数因子或者它本身就是质数 ...
- Codeforces 743C - Vladik and fractions (构造)
Codeforces Round #384 (Div. 2) 题目链接:Vladik and fractions Vladik and Chloe decided to determine who o ...
- Codeforces 1368E - Ski Accidents(构造+思维)
Codeforces 题面传送门 & 洛谷题面传送门 神仙构造题(不过可能我构造太烂了?) 首先考虑这个奇奇怪怪的 \(\dfrac{4}{7}\),以及这个每个点出度最多为 \(2\) 的条 ...
- Codeforces 1270E - Divide Points(构造+奇偶性)
Codeforces 题目传送门 & 洛谷题目传送门 显然,直接暴力枚举是不可能的. 考虑将点按横纵坐标奇偶性分组,记 \(S_{i,j}=\{t|x_t\equiv i\pmod{2},y_ ...
- codeforces 622C. Optimal Number Permutation 构造
题目链接 假设始终可以找到一种状态使得值为0, 那么两个1之间需要隔n-2个数, 两个2之间需要隔n-3个数, 两个3之间隔n-4个数. 我们发现两个三可以放到两个1之间, 同理两个5放到两个3之间. ...
随机推荐
- c#数据类型和表达式
一.数据类型 值类型: 1.整数(没有小数) Byte:字节0~255 Char:一个字符 Int 2.有小数 范围大的:double双 小范围:float单 最精确的:十进制decimal 3.bo ...
- Azure进阶攻略 | 你的程序也能察言观色?这个真的可以有!
前段时间有个网站曾经火爆微博和朋友圈:颜龄机器人.只要随便上传一张包含人面孔的照片,这个网站就可以分析图片,并判断照片中人物的年龄.化妆.美颜 P 图.帽子墨镜之类的配饰,几乎都没法影响这个网站的检测 ...
- linux单机限速工具
wondershaper是国外人开发的一款在Linux内核下基于TC工具的对整块网卡的限度工具. http://lartc.org/wondershaper/ 安装wondershaper: [roo ...
- python_opencv应用系列1:图片读写
opencv的读写非常简单,主要用到的就是imread和imwrite两个函数 读取图片示例 import cv2 #imread(filename[, flags]) -> retval im ...
- 【css基础修炼之路】— 谈谈元素的垂直水平居中
作为一个初级的前端工程师,在开发的过程中遇到了许多问题,其中使元素垂直居中这个问题难住了我,可能在大家看来这是一个非常小的问题,但是却困扰了我很长时间,于是决定做一个总结!!! 废话不多说,直接上代码 ...
- 如何把某个网站的SSL Server certificate链导入到ABAP Netweaver系统里
我们在用ABAP代码消费外网的url时会遇到一些异常,比如ICM_HTTP_SSL_PEER_CERT_UNTRUSTED,这是因为请求的url所在的网站的SSL Server certificate ...
- QT OpenGL中文教程在QT4版本后的错误代码更改(一)
由于教程中说的已经够可以了,这里就不对代码进行分析了,有兴趣可以自己去看看.这个教程来源于原来的NeHeOpenGL中文教程 (http://www.yakergong.net/nehe/) ,但其有 ...
- 后缀数组入门(二)——Height数组与LCP
前言 看这篇博客前,先去了解一下后缀数组的基本操作吧:后缀数组入门(一)--后缀排序. 这篇博客的内容,主要建立于后缀排序的基础之上,进一步研究一个\(Height\)数组以及如何求\(LCP\). ...
- 宝塔linux面板,修改root密码
root,密码忘记了.但宝塔vps的密码没忘记... 翻完宝塔linux面板都没看到有修改系统root密码的选项,后来尝试定时任务shell,也没成功, 最终快绝望的时候,发现通过添加插件成功修改密码 ...
- phpmyadmin 打开数据表较多,数据量较大的数据库时出现超时的解决办法
用phpmyadmin打开数据表较多,数据量较大的数据库时,会出现超时,或者等半天打开了说数据库没有表.并且即便打开了,再进行其他浏览,编辑,sql等操作,页面也是相当慢的,慢等几乎无法忍受.这里慢也 ...