2023年蓝桥杯C组省赛真题 填充 知识点:贪心

131 阅读2分钟

1.填充 - 蓝桥云课 (lanqiao.cn)

视频解析:[蓝桥杯]真题讲解:填充(贪心)_哔哩哔哩_bilibili

解析

对于这种多决策,且求最小值最大值问题,可以用爆搜枚举所有可能,找出合法的方案,最后在所有1合法方案中求出最大值。

假设有m个问号,每个问号都有变1或0两种选择,一共就有2^m种选择,假设m足够大,那么就会超时。

对于dfs拿不了满分的,往往有两种优解,一种是贪心,一种是dp。一般情况下贪心用于多种方案中给出一种最优策略,这种策略往往就是答案。倘若每一种策略都有反例,那就可以考虑一下dp。

对于本道题给出的贪心策略就是:

对于中间的字符而言,优先和前面的字符匹配。

比如说: 如果?号前面的1没有被匹配过,那么?号就和前面的1进行匹配,这样配下来,整个数组都是两两匹配。如果?号向后匹配,那么后面的数的选择就少了,甚至可能有元素最后没有字符匹配。

image.png image.png

code

#include<bits/stdc++.h>
using namespace std;
int ans;
int main()
{
	cin.tie(nullptr)->sync_with_stdio(false);
	string s; cin >> s;
	vector<bool>st(s.size());    //	用来标记当前字符是否已经被匹配
	for (int i = 0; i < s.size(); i++)
	{   
		//不是问号的情况
		if (s[i]!='?')
		{
			//如果前一个字符存在  且和当前字符一样  且没有被匹配过
			if (i - 1 >= 0 && s[i - 1] == s[i] && !st[i - 1])
			{
				//标记为已经匹配
				st[i - 1] = true;
				st[i] = true;
				ans++;  //方案数加1
			}
			else if (i+1<s.size()   and  s[i]==s[i+1]   and   !st[i])
			{
				st[i] = true;
				st[i + 1] = true;
				ans++;
			}

		}
		else   //问号的情况
		{
			if (st[i])continue;  //没匹配过才匹配

			//如果前一个字符存在    且没有被匹配过
			if (i - 1 >= 0&& !st[i - 1])
			{
				//标记为已经匹配
				st[i - 1] = true;
				st[i] = true;
				ans++;  //方案数加1
			}
			else if (i + 1 < s.size() and !st[i])
			{
				st[i] = true;
				st[i + 1] = true;
				ans++;
			}
		}
	}
	cout << ans << endl;
	return 0;
}

image.png