牛客多校2 A题
题意:
给定两种图形
A
,
B
A,B
A,B,要求构造一个
n
⋅
m
n \cdot m
n⋅m的由
A
,
B
A,B
A,B两种图案构成的矩形,同时满足矩形中的曲线数量恰好为
k
k
k个,并限制了某个
(
x
,
y
)
(x,y)
(x,y)位置上的图形必须为
A
A
A或者
B
B
B。
题解:
考虑从左上角开始构造,左上角第一个图案的贡献必然是
2
2
2,仅向右继续拼接时,无论是
A
A
A还是
B
B
B,每添加一个新的图案,贡献也必然是
1
1
1,向下同理,当第一行和第一列构造完后,其贡献值必然为
n
+
m
n + m
n+m,继续向右下角构造,我们可以发现每添加一个新的图案,其贡献要么为
1
1
1,要么为
0
0
0,所以显然,最终结果的最小值一定是
n
+
m
n + m
n+m,如果我们想让右下角的贡献为
1
1
1,我们可以构造出类似于单位圆一样的图形,每产生一个单位圆,总贡献值会
+
1
+1
+1,当且仅当
2
∗
2
2*2
2∗2的图案为
A
B
,
B
A
AB,BA
AB,BA时产生一个单位圆,那么显然我们只需要先去构造出最多的单位圆,判断答案是否小于当前图案且大于等于
n
+
m
n + m
n+m,如果符合要求,我们从左上角开始一行一行遍历,将
B
B
B变成
A
A
A或者将
A
A
A变成
B
B
B,这样可以实现一个一个消除单位圆,当剩余单位圆的数量满足条件时,输出答案即可。
还有一点需要注意的是题目限制了某个位置的固定图案,因此我们可以通过奇偶性去判断最多的单位圆图案的左上角应该是 A A A还是 B B B,然后按照原来的规则一步一步去消除单位圆即可。
#include<bits/stdc++.h>
using namespace std;
#define endl '\n'
#define int long long
#define debug(p) for (auto i : p)cerr << i << " "; cerr << endl;
#define debugs(p) for (auto i : p)cerr << i.first << " " << i.second << endl;
typedef pair<int, int> pll;
string yes = "Yes";
string no = "No";
int last = 0;
int area(int i, int j, int op)
{
int a = ((i - 1) * (j - 1) + 1) / 2;
int b = (i - 1) * (j - 1) / 2;
if(op == 1)return a;
else return b;
}
char ans[817][817];
void solve()
{
int n, m, k;
cin >> n >> m >> k;
int x, y;
string temp;
cin >> x >> y >> temp;
if(k < n + m)
{
cout << no << endl;
return;
}
if((x + y) % 2 == 0 && temp == "A" || (x + y) % 2 && temp == "B")last = 1;
else last = 2;
k -= (n + m);
if(last == 1)
{
for (int i = 1; i <= n; i++)
{
for (int j = 1; j <= m; j++)
{
if((i + j) % 2 == 0)ans[i][j] = 'A';
else ans[i][j] = 'B';
}
}
int tot = area(n, m, 1);
if(k > tot)
{
cout << no << endl;
return;
}
for (int j = 1; j <= m; j++)
{
if(tot == k)break;
for (int i = 1; i <= n; i++)
{
if(temp == "B")
{
if(i + 1 <= n && j + 1 <= m && ans[i][j] == 'A' && ans[i + 1][j + 1] == 'A' && ans[i + 1][j] == 'B' && ans[i][j + 1] == 'B')
{
tot--;
ans[i][j] = 'B';
}
ans[i][j] = 'B';
}
else
{
if(i - 1 > 0 && j + 1 <= m && ans[i][j] == 'B' && ans[i - 1][j + 1] == 'B' && ans[i - 1][j] == 'A' && ans[i][j + 1] == 'A')
{
tot--;
ans[i][j] = 'A';
}
ans[i][j] = 'A';
}
if(tot == k)break;
}
if(tot == k)break;
}
}
else
{
for (int i = 1; i <= n; i++)
{
for (int j = 1; j <= m; j++)
{
if((i + j) % 2 == 0)ans[i][j] = 'B';
else ans[i][j] = 'A';
}
}
int tot = area(n, m, 2);
if(k > tot)
{
cout << no << endl;
return;
}
for (int j = 1; j <= m; j++)
{
if(tot == k)break;
for (int i = 1; i <= n; i++)
{
if(temp == "B")
{
if(i + 1 <= n && j + 1 <= m && ans[i][j] == 'A' && ans[i + 1][j + 1] == 'A' && ans[i + 1][j] == 'B' && ans[i][j + 1] == 'B')
{
tot--;
ans[i][j] = 'B';
}
ans[i][j] = 'B';
}
else
{
if(i - 1 > 0 && j + 1 <= m && ans[i][j] == 'B' && ans[i - 1][j + 1] == 'B' && ans[i - 1][j] == 'A' && ans[i][j + 1] == 'A')
{
tot--;
ans[i][j] = 'A';
}
ans[i][j] = 'A';
}
if(tot == k)break;
}
if(tot == k)break;
}
}
cout << yes << endl;
for (int i = 1; i <= n; i++)
{
for (int j = 1; j <= m; j++)
{
cout << ans[i][j];
}
cout << endl;
}
}
signed main()
{
ios::sync_with_stdio(false);
cin.tie(0), cout.tie(0);
int T = 1;
cin >> T;
while (T--)
{
solve();
}
}