列表

详情


NC215088. 开心消消乐

描述

Hello 2021,
Goodbye 2020,
Cg本决定跨年之夜,应该不刷题,开心玩游戏,于是打开了开心消消乐..
这个消消乐版本特殊: 0与1相连指左边是0,右边是1)就会消掉这个01
游戏初始有一个01字符串,会自动消除,你要快速知道最后消除完成后的长度,例如:
10011 消除后就会变成1 (0011)被消除
Cg觉得这样太简单了,所以Cg在游戏开始之前可以进行一次操作,选择一段1的个数是0的个数两倍的区间,把这个区间消除,之后再进行上述游戏规则,问如何选取区间,使得剩下的字符串长度最小?
当然可以不进行操作哦!
注意如果进行操作:一定是操作完成后再消除

输入描述

第一行一个整数n,代表字符串长度
第二行一个字符串s,s由0、1组成,|s|<=10000

输出描述

一个整数ans,代表剩下的字符串长度最小是多少

示例1

输入:

5
10110

输出:

2

原站题解

上次编辑到这里,代码来自缓存 点击恢复默认模板

C++(clang++11) 解法, 执行用时: 80ms, 内存消耗: 632K, 提交时间: 2021-01-02 09:51:12

#include<bits/stdc++.h>
using namespace std;
const int maxn = 1e4 + 5;
pair<int,int>pre[maxn], suf[maxn];
int main(){
	int n;
	string st;
	cin >> n >> st;
	int a = 0, b = 0;
	for(int i = 0; i < n; i++){
		if(st[i] == '0')b++;
		else{
			if(b)b--;
			else a++; 
		}
		pre[i]={a,b};
    }
    a = b = 0;
	for(int i = n-1; i >= 0; i--){
		if(st[i] == '0'){
			if(a)a--;
			else b++;
		}else{
			a++;
		}
		suf[i] = {a,b};
	}
	int ans = pre[n-1].first + pre[n-1].second;
	for(int i = 0; i < n; i++){
		a = b = 0;
		for(int j = i; j < n; j++){
			if(st[j] == '0')a++;
			else b++;
			if(b == 2*a){
				int a1 = i?pre[i-1].first:0;
				int b1 = i?pre[i-1].second:0;
				int a2 = suf[j+1].first;
				int b2 = suf[j+1].second;
				ans = min(ans, a1+b2+abs(b1-a2));
			} 
		}
	}
	cout << ans << endl;
} 

上一题