【环】P6709 [CCC 2020] Swapping Seats 环|普及+

本文涉及的基础知识点

C++图论

P6709 CCC 2020 Swapping Seats

题目描述

有 N N N 个人坐在一张圆桌旁。

共有三个派别,每一个人属于一个派别。

现在,您想使属于同一派别的人坐到一起。

您可以每次将两个人交换位置,输出最小的交换次数。

输入格式

仅一行一个长度为 N N N 的字符串 s s s,为顺时针所有人的派别。

如果 s i s_i si 为 A,则说明第 i i i 个人为第一个派别的,以此类推。

输出格式

仅一行一个整数,表示最小的交换次数。

输入输出样例 #1

输入 #1

复制代码
BABCBCACCA

输出 #1

复制代码
2

说明/提示

样例解释

BABCBCACCA → AABCBCBCCA → AABBBCCCCA \texttt{BABCBCACCA}\to\texttt{AABCBCBCCA}\to\texttt{AABBBCCCCA} BABCBCACCA→AABCBCBCCA→AABBBCCCCA。

子任务

本题采用捆绑测试,且本题的 Subtask 分数有微调。

  • Subtask 1( 26 26 26 分): s i ∈ { s_i\in\{ si∈{A , , ,B } \} } 且 N ≤ 5 × 10 3 N\le 5\times 10^3 N≤5×103。
  • Subtask 2( 27 27 27 分): s i ∈ { s_i\in\{ si∈{A , , ,B } \} }。
  • Subtask 3( 27 27 27 分): N ≤ 5 × 10 3 N\le 5\times 10^3 N≤5×103。
  • Subtask 4( 20 20 20 分):无特殊限制。

对于 100 % 100\% 100% 的数据,保证 s i ∈ { s_i\in\{ si∈{A , , ,B , , ,C } \} }, 1 ≤ N ≤ 10 6 1\le N\le 10^6 1≤N≤106。

说明

本题译自 Canadian Computing Competition 2020 Senior T4 Swapping Seats。

环

n1=A派的数量,n2=B派的数量,n3=C派的数量。

如果x派的人,需要去y派坐着的座位,则增加x → \rightarrow → y。最终有向图一定是若干个环。不失一般性,某路径以A为起点,无环的两条边路径只有ABC和ACB。第四点一定是环。排除自环后,只有两条边的环和三条边的环。2条边的环,只需要一次交换;3条边的环,需要2次交换。

cntij 记录(A+i)到(A + j)的边的数量。

统计完2边环,剩余的都是3边环。

f(i)函数:位置i是A,且他的左边没有A,右边依次是BC。

f(0):一,i ∈ \in ∈0,n1-1 cnt0s\[i-'A']++ 二,i ∈ \in ∈n1,n1+n2-1 , c n t 1 s \[ i − ′ A ′ ] + + ,三, i , cnt1s\[i-'A']++ ,三,i ,cnt1s\[i−′A′]++,三,i\in$n1+n2,N-1,cnt2s\[i-'A']++。

f(i)迭代成f(i+1):

i号位由A变成C,i+n1号位由B变成A,i+n1+n2有C变成B。

i号位由A变成C

cnt0s\[i-'A']--

cnt2s\[i-'A']++

注意:枚举完ABC,还需要枚举ACB。可以直接原始串的BC互换。

代码

核心代码

cpp 复制代码
#include <iostream>
#include <sstream>
#include <vector>
#include<map>
#include<unordered_map>
#include<set>
#include<unordered_set>
#include<string>
#include<algorithm>
#include<functional>
#include<queue>
#include <stack>
#include<iomanip>
#include<numeric>
#include <math.h>
#include <climits>
#include<assert.h>
#include<cstring>
#include<list>

#include <bitset>
using namespace std;

class Solution {
public:
	int Ans(const string& s) {
		string acb = s;;
		for (auto& ch : acb) {
			if ('B' == ch) { ch = 'C'; }
			else if ('C' == ch) { ch = 'B'; }
		}
		return min(Check(s), Check(acb));
	}
	int Check(const string& s) {
		const int N = s.length();
		int n1 = 0, n2 = 0;
		for (const auto& ch : s) {
			n1 += ('A' == ch);
			n2 += ('B' == ch);
		}
		int cnt[3][3] = { 0 };
		auto Need = [&]() {
			int remain = 0;
			int ring2 = 0;
			for (int i = 0; i < 3; i++) {
				const int i2 = (i + 1) % 3;
				const int m1 = min(cnt[i][i2], cnt[i2][i]);
				const int m2 = max(cnt[i][i2], cnt[i2][i]);
				ring2 += m1;
				remain += m2 - m1;
			}
			return ring2 + remain / 3 * 2;
		};
		int i = 0;
		for (; i < n1; i++) {
			cnt[0][s[i] - 'A']++;
		}
		for (; i < n1 + n2; i++) {
			cnt[1][s[i] - 'A']++;
		}
		for (; i < N; i++) {
			cnt[2][s[i] - 'A']++;
		}
		int ans = Need();
		for (int i = 0; i + 1 < N; i++) {
			const int i2 = (i + n1) % N;
			const int i3 = (i + n1 + n2) % N;
			cnt[0][s[i] - 'A']--;
			cnt[2][s[i] - 'A']++;
			cnt[1][s[i2] - 'A']--;
			cnt[0][s[i2] - 'A']++;
			cnt[2][s[i3] - 'A']--;
			cnt[1][s[i3] - 'A']++;
			ans = min(ans, Need());
		}
		return ans;
	}
};




        
int main() {
#ifdef _DEBUG
	freopen("a.in", "r", stdin);
#endif // DEBUG	
	ios::sync_with_stdio(0); cin.tie(nullptr);
	string s;
	cin >> s;
	
#ifdef _DEBUG		
	//printf("N=%d",n);
	//cout << ",s=" << s;
	//Out(edge, ",edge=");
	//Out(que, ",que=");
	//Out(que, ",que=");
	/*Out(que, "que=");*/
#endif // DEBUG		
	auto res = Solution().Ans(s);
	cout << res << '\n';
	return 0;
}

单元测试

cpp 复制代码
	vector < int> hs, ws;
		TEST_METHOD(TestMethod11)
		{
			Solution slu;
			auto res = slu.Ans("BABCBCACCA");
			AssertEx(2, res);
		}

扩展阅读

算法为骨,CAD为魂
亲士工具箱:支持中望CAD2024、AutoCad2013及以上,多年承接CAD项目的精华
工作中遇到的问题,可以按类别查阅鄙人的算法文章,请点击《算法与数据汇总》。
学习算法:按章节学习《喜缺全书算法册》,大量的题目和测试用例,打包下载。重视操作
活到老,学到老。明朝中后期,大约50%的进士能当上堂官(副部及更高);能当上堂官的举人只有十余人。
子墨子言之:事无终始,无务多业。也就是我们常说的专业的人做专业的事。

视频课程

先学简单的课程,请移步CSDN学院,听白银讲师(也就是鄙人)的讲解。

https://edu.csdn.net/course/detail/38771

如何你想快速形成战斗了,为老板分忧,请学习C#入职培训、C++入职培训等课程

https://edu.csdn.net/lecturer/6176

测试环境

操作系统:win7 开发环境: VS2019 C++17

或者 操作系统:win10 开发环境: VS2022 C++17

如无特殊说明,本算法用**C++**实现。

相关推荐
开开心心就好1 小时前
打印机卡住打不了?一键清理卡死打印队列
服务器·开发语言·算法·pdf·ocr·idea·visual studio code
格物致胜工业数智技术1 小时前
锂电纠偏测量那些坑,明治ETD-0612激光纠偏传感器怎么填?
人工智能·算法
垆边人似月.1 小时前
带权区间调度,优先级可负
算法
重生之小比特1 小时前
【算法拾光】双指针|三数之和 + 四数之和
算法
我爱工作&工作love我1 小时前
P14359 [CSP-J 2025] 异或和
算法
茉莉玫瑰花茶1 小时前
GO [ 数据格式 ]
服务器·网络·算法·golang
小poop1 小时前
高级排序算法与性能对比——归并、非比较排序及总结
数据结构·算法·排序算法
aqiu1111111 小时前
CodeTop按顺序刷题0003:LeetCode 206. 反转链表(迭代法图文详解与动态演示)
算法·leetcode·链表
果霸大叔2 小时前
AI网关第8篇:AI 代理与负载均衡--多模型实例如何调度?
人工智能·算法·自然语言处理·负载均衡·ai-native