利用贪心算法构造01串

题目描述

小红希望你构造一个由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,则直接将剩余的字符添加到结果中。
添加剩余的字符

ab 中仍有剩余字符的情况下,继续添加这些字符到结果中。

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;
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值