【代码超详解】CometOJ C1749 [CCPC2017秦皇岛站-C] Crusaders Quest(暴力枚举,34 ms)

一、题目描述

在这里插入图片描述

二、算法分析说明与代码编写指导

数据量较小,因此考虑暴力枚举。
将字符存入 s,并分成几个连续的块,将这些块的起始位置和长度分别记录,塞入向量 v 中。例如第一个样例的 gggaaaooo 会在 v 中产生如下记录:
{0, 3},{3, 3},{6, 3}。
采用这样的记录方式是为了方便直接使用 std::string::erase() 的第 3 个重载:
在这里插入图片描述
然后通过递归进行暴力枚举,即尝试删除每个块,并枚举删除该块后可能的继续删除的情况。递归函数的第一个参数是剩余的字符 s,第二个参数是长为 3 的块的数量。如果能删除长度为 3 的块,第二个参数就要 +1,并进入深一层递归继续枚举删除该块的情况。否则两个参数都不变,直接进入深层递归继续枚举删除该块后的情况。
在编写递归函数的时候要注意,9 个字符都删除完毕后递归要中止。而为了考察删除任意一个连续的块后,到底还要删除哪些块使得可以删除长度为 3 的块,对剩余的块仍然需要逐个枚举删除的情形。所以必须在每层递归中单独建立字符串 t 临时存储剩余的字符 s,这样当一种情况枚举完毕(剩余字符为 0)并从深层递归返回后,剩余的字符串也就相应地回滚到了本层递归的情形。

三、AC 代码

#include<iostream>
#include<string>
#include<map>
#include<vector>
#include<algorithm>
using namespace std;
#pragma warning(disable:4996)
string s; size_t t, a;
void solve(string& s, const size_t& l) {
	if (s.empty() == true) { a = max(a, l); return; }
	vector<pair<size_t, size_t>> v; size_t b = 0; string t;
	for (size_t i = 0; i < s.size(); ++i) {
		if (s[b] != s[i]) { v.emplace_back(make_pair(b, i - b)); b = i; }
	}
	v.emplace_back(b, s.size() - b);
	for (size_t i = 0; i < v.size(); ++i) {
		t = s; t.erase(v[i].first, v[i].second);
		if (v[i].second == 3)solve(t, l + 1);
		else solve(t, l);
	}
}
int main() {
	ios::sync_with_stdio(false); cin.tie(0);
	cin >> t; ++t;
	while (--t) {
		cin >> s; a = 0; solve(s, 0); cout << a << endl;
	}
	return 0;
}
发布了214 篇原创文章 · 获赞 19 · 访问量 1万+

猜你喜欢

转载自blog.csdn.net/COFACTOR/article/details/104076049
今日推荐