acwing3777-砖块题解(南昌理工学院ACM暑假集训队)


话不多说直接上题目!!

一、题目

点击下面啦!
砖块

n 个砖块排成一排,从左到右编号依次为 1∼n。

每个砖块要么是黑色的,要么是白色的。

现在你可以进行以下操作若干次(可以是 0 次):

选择两个相邻的砖块,反转它们的颜色。(黑变白,白变黑)

你的目标是通过不超过 3n 次操作,将所有砖块的颜色变得一致。

输入格式
第一行包含整数 T,表示共有 T 组测试数据。

每组数据第一行包含一个整数 n。

第二行包含一个长度为 n 的字符串 s。其中的每个字符都是 W 或 B,如果第 i 个字符是 W,则表示第 i 号砖块是白色的,如果第 i 个字符是 B,则表示第 i 个砖块是黑色的。

输出格式
每组数据,如果无解则输出一行 −1。

否则,首先输出一行 k,表示需要的操作次数。

如果 k>0,则还需再输出一行 k 个整数,p1,p2,…,pk。其中 pi 表示第 i 次操作,选中的砖块为 pi 和 pi+1 号砖块。

如果方案不唯一,则输出任意合理方案即可。

数据范围
1≤T≤10,
2≤n≤200。

输入样例:
4
8
BWWWWWWB
4
BWBB
5
WWWWW
3
BWB
输出样例:
3
6 2 4
-1
0
2
2 1

注意!答案不唯一,那么我们直接看例子!还有就是两个相邻的字母都改变!今天我们用O(1)复杂度来解决这个简单问题!

二、思路

1.

目标是通过不超过 3n 次操作,将所有砖块的颜色变得一致。
我们先设置两个变量cntb,和cntw分别表示字符串中字母为’B’的个数,和字符串中字母为’W’的个数。
先来看第一个例子,我们可以看出cntb和cntw都为偶数,并且我们可以发现无论把结果变成全为”B“还是”W“都为正确答案!

if (cntb % 2 == 0 && cntw % 2 == 0) {
			for (int i = 1; i < len; i++)
			{
				if (a[i] != a[0]) {
					if (a[i + 1] == 'B')a[i + 1] = 'W';
					else a[i + 1] = 'B';
					q.push(i+1);
				}
			}
			cout << q.size() << endl;
			while (!q.empty()) {
				cout << q.front() << " "; q.pop();
			}
			cout << endl;
			continue;
		}

再看第二个例子,我们看出cntb和cntw都为奇数,我们可以举出例子,当cntb和cntw都为奇数的时候,答案其实是无解的:
eg:BWWW变成BBBW无解,BBBWWW变成BBBBBW也无解,因为最终改变的结果有一个单独的字母,所以我们可以得到字母都为奇数的情况下无解

if (cntw % 2 == 1 && cntb % 2 == 1) {
			cout << -1 << endl; continue;
		}

第三个例子,那就是cntb和cntw有一个为0,也就是本来就是同色,直接输出0即可!

if (cntw == 0 || cntb == 0) {
			cout << 0 << endl; continue;
		}

第四个例子,那就是cntb和cntw有一个为偶数,一个为奇数。由第二个例子可以得出,在第二个例子最后的改变中,再加一个可以改变的字母,结果就能全部变成同色!
eg:BWW变成BBB,BBWWW变成WWWWW
而且不能发现只能改变成字母数为奇数的那个字母!
在这里分两种,一种是cntb为奇数,另一种是cntw为奇数

if (cntw % 2 == 1) {
			for (int i = 0; i < len; i++)
			{
				if (a[i] == 'B') {
					q.push(i+1);
					if (a[i + 1] == 'W')a[i + 1] = 'B';
					else a[i + 1] = 'W';
				}
			}
			cout << q.size() << endl;
			while (!q.empty()) {
				cout << q.front() << " "; q.pop();
			}
			cout << endl;
			continue;
		}
		if (cntb % 2 == 1) {
			for (int i = 0; i < len; i++)
			{
				if (a[i] == 'W') {
					p.push(i+1);
					if (a[i + 1] == 'W')a[i + 1] = 'B';
					else a[i + 1] = 'W';
				}
			}
			cout << p.size() << endl;
			while (!p.empty()) {
				cout << p.front() << " "; p.pop();
			}
			cout << endl;
			continue;
		}

代码

不难发现我们用规律的方式也可以写出这道题,我看了一下其他人用dp做的,可能我dp学的不太行吧,嘻嘻本人蒟蒻!

using namespace std;
int t, n;
int main()
{
	cin >> t;
	while (t--)
	{
		cin >> n;
		string a;
		cin >> a;
		queue<int> q,p;
		int cntw = 0, cntb = 0;
		int len = a.length();
		for (int i = 0; i < len; i++)
		{
			if (a[i] == 'W')cntw++; else cntb++;
		}
		if (cntw % 2 == 1 && cntb % 2 == 1) {
			cout << -1 << endl; continue;
		}
		else if (cntw == 0 || cntb == 0) {
			cout << 0 << endl; continue;
		}
		if (cntw % 2 == 1) {
			for (int i = 0; i < len; i++)
			{
				if (a[i] == 'B') {
					q.push(i+1);
					if (a[i + 1] == 'W')a[i + 1] = 'B';
					else a[i + 1] = 'W';
				}
			}
			cout << q.size() << endl;
			while (!q.empty()) {
				cout << q.front() << " "; q.pop();
			}
			cout << endl;
			continue;
		}
		if (cntb % 2 == 1) {
			for (int i = 0; i < len; i++)
			{
				if (a[i] == 'W') {
					p.push(i+1);
					if (a[i + 1] == 'W')a[i + 1] = 'B';
					else a[i + 1] = 'W';
				}
			}
			cout << p.size() << endl;
			while (!p.empty()) {
				cout << p.front() << " "; p.pop();
			}
			cout << endl;
			continue;
		}
		if (cntb % 2 == 0 && cntw % 2 == 0) {
			for (int i = 1; i < len; i++)
			{
				if (a[i] != a[0]) {
					if (a[i + 1] == 'B')a[i + 1] = 'W';
					else a[i + 1] = 'B';
					q.push(i+1);
				}
			}
			cout << q.size() << endl;
			while (!q.empty()) {
				cout << q.front() << " "; q.pop();
			}
			cout << endl;
			continue;
		}
	}
}
内容较大,权限不够,故将内容分为六个部分,需要的请自行下载。 教程版权归原作者所有,本人只是负责搜集整理,本人不承担任何技术及版权问题。教程仅提供学习参考,不得用于商业用途,请在下载后在24小时内删除。 目录: 0001-2科技发展有限公司升级版源码 0001科技发展有限公司修正版源码 0002机械配件制造销售公司修正版源码 0003家具地板公司修正版源码 0004-1机械有限公司修正版源码 0004机械有限公司修正版源码 0005机械产品公司修正版源码 0006绿色环保集团股份有限公司优化版 0007金属材料制品公司修正版源码 0008电气股份有限公司修正版源码 0009红色风格设备有限公司修正版源码 0010蓝色仪表配件有限公司优化版 0011装修公司网站系统修正版源码 0012环保工程企业网站修正版源码 0013国际集团股份有限公司修正版源码 0014蓝色汽车配件有限公司修正版源码 0015家俱集团有限公司源码 0016典雅地板家居网站源码 0017蓝色企业网站系统二 0018国际集团机械仪器公司修正版源码次优化版 0019红色风格企业网站系统优化版 0020机械设备公司修正版源码 0021蓝色环保工程企业网站系统修正版源码 0022国际集团电子科技公司修正版源码 0023国际集团机械电子公司修正版源码 0024美工超级漂亮的ASP卫生纸公司修正版源码 0025绿色环境保护工程公司修正版源码 0026绿色环保生态园林公司修正版源码 0028蓝色机械制造科技公司优化版 0029装修装饰公司企业网站修正版源码 0030绿色风格酒店网站修正版源码 0031机械制造网站修正版源码 0032蓝色机械制造公司修正版源码 0033机械设备制造公司修正版源码 0034ASP机械制造企业修正版源码 0035红色汽车配件公司网站修正版源码 0036机械制造企业修正版源码 0037机械设备公司修正版源码 0038浅蓝色电子科技公司修正版源码 0039机械制造公司企业网站修正版源码 0040国际集团机械有限公司修正版源码 0041机械设备公司优化版 0042机械企业修正版源码 0043机械设备有限公司修正版源码 0044红色机械设备有限公司修政版源码 0045汽车配件制造公司修正版源码 0046蓝色汽配公司修正版源码 0047绿色园林环保公司优化版 0048红色机械化工公司修正版源码 0049机械设备有限公司修正版源码 0051测试完整无错的经典万能企业站程序 0052某电气工程有限公司源码 0053优乐博特自动化工程有限公司网站源码
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值