P8153 题解

思路来自:@wsyear 大佬,十分感谢。

题意:

给你 \(n\)\(01\) 字符串,每次取一个串后删除第一个字符,将剩下的串加入到答案串中,最大化答案串中相邻字符相等的对数。

思路:

  • Sub1:爆搜。

我的爆搜写的比较奇怪。

记录
暴力代码

  • Sub2,Sub3

我们考虑贪心,首先我们把所有的字串全加进去是最优的,因为有更多的字符就有更多的可能去最大化答案串中相邻字符相等的对数。

既然是全加进去,每个字串中间是什么无法改变,只能改变头尾相接的顺序,所以我们预处理出所有串的字串中相等的对数。

这个时候我们就只需要考虑每个串的头和尾了,头尾相接有 \(4\) 中情况:

  • \(1 \ 0\)

  • \(1 \ 1\)

  • \(0 \ 1\)

  • \(0 \ 0\)

我们只需要统计出以 \(1\) 为前缀,后缀的串的个数,以 \(0\) 为前缀的串的个数即可。

我们还要考虑这个答案串一开始是要填 \(0\) 还是填 \(1\)

所以我们将一开始填 \(0\) 和一开始填 \(1\) 的情况做比较即可。

AC code:

/*
work by: TLE_Automation
Time: O(轻轻松松过)
knowledge: 垃圾算法
*/
#include<bits/stdc++.h>
#define il inline
#define re register
#define Orz puts("Szt Lps Fjh AK IOI!");
#define IOS ios::sync_with_stdio(false), cin.tie(0), cout.tie(0);
// #define int long long
using namespace std;

const int INF = 1e9 + 7, mod = 1e9 + 7;
const int maxn = 2e5 + 10, MAXN = 3e3 + 10, N = 1e6 + 10;

typedef long long LL;
string s[N];
LL ans, n;
int L[N], sum = 0;
bool f1, f2; 
int sum1, sum2, sum3, sum4;
 
// sum1 是以 0 为后缀的串的个数 
// sum2 是以 1 为后缀的串的个数 
// sum3 是以 0 为前缀的串的个数 
// sum4 是以 1 为前缀的串的个数 
// f1 是否有开头就是 0 的
// f2 是否有开头就是 1 的
 
signed main() {
	IOS
	cin >> n;
	for(re int i = 1; i <= n; i++) cin >> s[i], s[i] = "$" + s[i], L[i] = s[i].length() - 1;
	for(re int i = 1; i <= n; i++) sum += L[i];
//	for(int i = 1; i <= n; i++) cout << L[i] << " ";
	if(!(sum ^ n)) return printf("0"), 0;
	for(re int i = 1; i <= n; i++) {
		int cnt = 0; 
		for(re int j = L[i] - 1; j >= 2; j--) {
			if(s[i][j] == s[i][j + 1]) cnt++;
			ans += cnt;
		}
	}
//	cout << ans << endl; 
	for(re int i = 1; i <= n; i++) {
		if(L[i] == 1) continue; // 长度为 1 的串删完就成了空串,没用 
 		if(s[i][L[i]] == '0') sum1 += L[i] - 1; 
		else sum2 += L[i] - 1;		
		for(re int j = 2; j <= L[i]; j++) {
			if(s[i][j] == '0') sum3++;  
			else sum4++;
		}
		if(s[i][2] == '0') f1 = true;
		else if(s[i][2] == '1') f2 = true;	
	}
	if(f1 && f2) ans += max(min(sum3, sum1) + min(sum4 - 1, sum2), min(sum3 - 1, sum1) + min(sum4, sum2));
	else if(f1) ans += min(sum3 - 1, sum1) + min(sum4, sum2);
	else ans += min(sum3, sum1) + min(sum4 - 1, sum2);
	cout << ans << endl;
}
posted @ 2022-05-20 19:58  TLE_Automation  阅读(292)  评论(0编辑  收藏  举报