Codeforces Round #608 (Div. 2)B. Blocks

状态:WA

跑到第5个用例结果错了。分析了一波:CODEFORCES给这个题的标签是“greedy”“math”,呃,但是我没用什么算法。就找了一下规律。看来需要去看看贪婪算法是会有什么帮助吧。

题意很简单,“给相邻的两个色块进行取反操作,如果不能在3n次操作之后将颜色统一,那么输出-1;如果可以在3n次操作之内统一颜色,那么输出在哪些色块上进行取反操作”,大概是这个意思,具体还要看看题目。

能否进行颜色统一很好判断,如果不同色块的数目均为奇数,就不可能实现颜色统一。

但是对可以颜色统一的情况进行操作的时候,就有点让人头大了。时间不够,改日优化

#include <iostream>
#include <vector>
#include <cstring>
#include <string>
#include <map>
#include <math.h>
#include <algorithm>
#include <stdio.h>
#include <windows.h>
#include <deque>
#include <unordered_set>
#include <stack>
using namespace std;

int g_pos;
vector<int> g_result;

class Operator {
public:
	void scan(string &s, int sub_len);
	void reverse(char &si);
	int check(string s, int len);
	int correct(string s);
private:
	int opt_count;
};
void Operator::scan(string &s, int sub_len) {
	int i = 0;
	int j = 1;
	string ss(s.begin()+ g_pos,s.begin()+g_pos+sub_len);
	while (j < sub_len-1) {
		if (correct(ss))
			break;
		if (s[g_pos + i] != s[g_pos + j]) {
			i++;
			j++;
			continue;
		}
		else {
			reverse(s[g_pos + i]);
			reverse(s[g_pos + j]);
			g_result.push_back(g_pos + i + 1);
			opt_count++;
			i++;
			j++;
		}
	}
	if (opt_count) {
		opt_count = 0;
		return;
	}
	else {
		g_result.push_back(g_pos + 1);
		g_result.push_back(g_pos + 2);
		opt_count = 0;
	}
}
void Operator::reverse(char &si) {
	if (si == 'B')
		si = 'W';
	else
		si = 'B';
}
int Operator::check(string s, int len) {
	int cnt = 0;
	for (char mem : s) {
		if (mem == 'B')
			cnt++;
	}
	if (cnt % 2 && !(len % 2))
		return -1;
	return 0;
}
int Operator::correct(string s) {
	int ret = s[0];
	for (char mem : s) {
		if (!ret&mem)
			return 0;
		ret = mem;
	}
	return 1;
}

int main() {
	int total;
	string str;
	Operator opt;
	cin >> total;
	cin >> str;
	if (!opt.check(str, total)) {
	lable1:
		int B_flag = 0;
		int W_flag = 0;
		int pos = 0;
		do{
			if (str[pos] == 'B') {
				B_flag++;
				if ((B_flag >= 2) && (W_flag >= 2)) {
					opt.scan(str, g_pos + pos + 1);
					g_pos += pos;
				}
			}
			else {
				W_flag++;
				if ((B_flag >= 2) && (W_flag >= 2)) {
					opt.scan(str, g_pos + pos + 1);
					g_pos += pos;
				}
			}
			pos++;
		} while (pos < str.size());
		if (opt.correct(str)) {
			cout << (g_result.size()) << endl;
			for (auto mem : g_result) {
				cout << mem << " ";
			}
		}
		else {
			goto lable1;
		}
	}
	else {
		cout << -1;
	}
	return 0;
}


 

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值