题目 | Merge the squares
2023牛客暑期多校训练营4
H - Merge the squares!
https://ac.nowcoder.com/acm/contest/57358/H
题意
给定
题解
这道题是一道构造题,重点是找到一个通用的构造方法。
对于一个边长为
对于分出来的正方形,可以一直递归下去解决。先假定递归能够成功回来,那么边长为
接下来的问题就是,如何判定能在
先用宽做边长,切出几个正方形,再用剩下的长方形的宽做边长,切出几个正方形,一直这样下去直到全部切成正方形,最后把数目统计出来即可。如果切出的数目
那对于一个边长为
预处理好后就可以开始正式计算了,使用递归分治的思想。对于边长为
- 如果
:结束算法 如果
:在预处理的表中查询到正确切法如果查到可以直接合并
- 储存合并方式后直接结束
如果查到需要切割
- 储存合并方式
- 递归处理左上
正方形 - 递归处理右下
正方形 - 递归处理左下
长方形 - 递归处理右上
长方形
对于边长
- 如果边长为
:结束算法 如果边长都不为
:从切出的第
个正方形遍历到第 个正方形:- 递归处理每一个正方形
- 递归处理剩下的长方形
代码
#include <bits/stdc++.h>
#define endl '\n'
// #define int long long
using namespace std;
constexpr int MAXN = 1010;
int split[MAXN];
vector<array<int, 3>> res;
// a-lu b-rd
bool check_split(int a, int b)
{
if (!b)
return a <= 7;
int ans = 0;
while (b)
{
ans += a / b;
a %= b;
swap(a, b);
}
return ans <= 24;
}
void init_split(int n)
{
for (int i = 1; i <= n; i++)
{
for (int j = 0; j <= i / 2; j++)
{
// i - j >= j
if (check_split(i - j, j))
{
split[i] = j;
break;
}
}
}
// for (int i = 1; i <= n; i++)
// cout << split[i] << " \n"[i == n];
}
void dfs(int x, int y, int a);
void dfs_hori(int x, int y, int r, int c);
void dfs_vert(int x, int y, int r, int c);
void dfs_hori(int x, int y, int r, int c)
{
if (r < 1 || c < 1)
return;
int cnt = c / r;
for (int i = 0; i < cnt; i++)
dfs(x, y + i * r, r);
dfs_vert(x, y + cnt * r, r, c % r);
}
void dfs_vert(int x, int y, int r, int c)
{
if (r < 1 || c < 1)
return;
int cnt = r / c;
for (int i = 0; i < cnt; i++)
dfs(x + i * c, y, c);
dfs_hori(x + cnt * c, y, r % c, c);
}
void dfs(int x, int y, int a)
{
if (a == 1)
return;
res.push_back({x, y, a});
if (split[a] == 0)
return;
int lu = a - split[a], rd = split[a];
dfs(x, y, lu);
dfs(x + lu, y + lu, rd);
dfs_hori(x + lu, y, rd, lu);
dfs_vert(x, y + lu, lu, rd);
}
void solve()
{
int n;
cin >> n;
init_split(n);
dfs(1, 1, n);
cout << res.size() << endl;
for (int i = res.size() - 1; i >= 0; i--)
cout << res[i][0] << ' ' << res[i][1] << ' ' << res[i][2] << endl;
}
signed main()
{
ios::sync_with_stdio(false);
cin.tie(0);
cout.tie(0);
int t = 1;
// cin >> t;
while (t--)
solve();
return 0;
}
本文采用 CC BY-SA 4.0 许可,本文 Markdown 源码:Haotian-BiJi