题目描述
小红希望你构造一个由a个'0'、b个'1'组成的01串,该01串有恰好k对相邻的字符不同。
输入描述:
第一行一个整数t,表示测试样例数。 接下来t行,每行三个整数a,b,k用空格隔开。 1≤t≤10^4 0≤a,b,k≤10^5 a+b>0
保证所有测试样例的a+b的和不超过5×10^5
输出描述:
对于每组测试样例,如果无解,请输出-1。 否则输出一个长度为a+b的01串。有多解时输出任意即可。
示例1
输入
2 2 3 3 1 1 1
输出
01011 01
说明
对于第一组样例,输出11010也是可以的。
代码
#include <iostream>
#include <string>
using namespace std;
int main()
{
int t;
cin >> t;
while (t--)
{
int a, b, k;
cin >> a >> b >> k;
if (a + b - 1 < k)
{
cout << "-1" << endl;
continue;
}
string result;
int diff_count = 0;
// 贪心地构造字符串
while (a > 0 && b > 0)
{
if (diff_count < k)
{
if (a >= b)
{
result += "0";
a--;
if (a > 0)
{
result += "0";
a--;
}
}
else
{
result += "1";
b--;
if (b > 0)
{
result += "1";
b--;
}
}
diff_count++;
}
else
{
// 剩余的字符直接添加
if (a > 0)
{
result += "0";
a--;
}
if (b > 0)
{
result += "1";
b--;
}
}
}
// 添加剩余的字符
while (a > 0)
{
result += "0";
a--;
}
while (b > 0)
{
result += "1";
b--;
}
// 调整字符串以确保恰好 k 对相邻不同
if (diff_count < k)
{
for (int i = 0; i < result.size() - 1; i++)
{
if (result[i] == result[i + 1])
{
swap(result[i], result[i + 1]);
diff_count++;
if (diff_count == k) break;
}
}
}
// 再次检查是否满足条件
if (diff_count != k)
{
cout << "-1" << endl;
}
else
{
cout << result << endl;
}
}
return 0;
}
算法步骤
1. 输入处理
首先,读取测试样例的数量 t
。对于每个测试样例,读取三个整数 a
('0' 的数量)、b
('1' 的数量)和 k
(相邻不同的对数)。
int t;
cin >> t;
while (t--) {
int a, b, k;
cin >> a >> b >> k;
2. 初始检查
如果 a + b - 1 < k
,则无法构造这样的字符串,因为最多只能有 a + b - 1
对相邻的不同字符。在这种情况下,直接输出 -1
并跳到下一个测试样例。
if (a + b - 1 < k) {
cout << "-1" << endl;
continue;
}
3. 构建字符串
使用贪心算法来构建字符串,使得相邻不同的对数尽可能多。
初始化变量
result
:存储最终构造的字符串。diff_count
:记录当前相邻不同的对数。
string result;
int diff_count = 0;
贪心地构造字符串
- 在
a
和b
都大于 0 的情况下,交替放置 '0' 和 '1'。 - 如果当前相邻不同的对数少于
k
,则尽量交替放置字符以增加相邻不同的对数。 - 否则,直接添加剩余的字符。
while (a > 0 && b > 0) {
if (diff_count < k) {
if (a >= b) {
result += "0";
a--;
if (a > 0) {
result += "0";
a--;
}
} else {
result += "1";
b--;
if (b > 0) {
result += "1";
b--;
}
}
diff_count++;
} else {
// 剩余的字符直接添加
if (a > 0) {
result += "0";
a--;
}
if (b > 0) {
result += "1";
b--;
}
}
}
-
交替放置字符:
- 如果
a
大于等于b
,先添加两个 '0',然后减少a
的计数。 - 否则,先添加两个 '1',然后减少
b
的计数。 - 每次添加后增加
diff_count
,表示新增了一对相邻不同的字符。
- 如果
-
直接添加剩余字符:
- 如果已经达到了所需的相邻不同对数
k
,则直接将剩余的字符添加到结果中。
- 如果已经达到了所需的相邻不同对数
添加剩余的字符
在 a
或 b
中仍有剩余字符的情况下,继续添加这些字符到结果中。
while (a > 0) {
result += "0";
a--;
}
while (b > 0) {
result += "1";
b--;
}
4. 调整字符串
如果构建完成后相邻不同的对数仍少于 k
,尝试通过交换相邻相同的字符来增加相邻不同的对数。
if (diff_count < k) {
for (int i = 0; i < result.size() - 1; i++) {
if (result[i] == result[i + 1]) {
swap(result[i], result[i + 1]);
diff_count++;
if (diff_count == k) break;
}
}
}
- 交换相邻相同的字符:
- 遍历结果字符串,找到相邻相同的字符对。
- 交换这两个字符,从而增加相邻不同的对数。
- 每次交换后增加
diff_count
,直到达到所需的相邻不同对数k
。
5. 输出结果
最后,检查最终的相邻不同对数是否等于 k
。如果是,则输出构造的字符串;否则,输出 -1
。
if (diff_count != k) {
cout << "-1" << endl;
} else {
cout << result << endl;
}