[ABC227E] Swap 题解

考试一道题题解。


30pts:枚举所有串,\(check\) 是否可行。

60pts:做 \(bfs\),暴力推演变化过程,用 \(map\) 去重,时间复杂度 \(O(nC_{n}^{n/3}C_{n-n/3}^{n/3})\)

#include<bits/stdc++.h>
#define ll long long
using namespace std;
unordered_map<string,int>mp;
string s;int k;
ll ans=1;
struct zjy{
	string s;int b;
};queue<zjy>q;
int main(){
	ios::sync_with_stdio(0);
	cin.tie(0);cout.tie(0);
	cin>>s>>k;mp[s]=1;
	q.push({s,0});
	while(q.size()){
		int b=q.front().b+1;
		s=q.front().s;q.pop();
		if(b>k) continue;
		for(int i=1;s[i];i++){
			swap(s[i-1],s[i]);
			if(!mp[s])
				mp[s]=1,q.push({s,b}),ans++;
			swap(s[i-1],s[i]);
		}
	}cout<<ans;
	return 0;
}

100pts:

考虑到同种字符相对位置不可能发生改变,所以可以直接一个一个加入字符,然后加上将他移动到这里的代价。

\(dp_{i,j,k,l}\) 表示前 \(i+j+k\) 位用了 \(i\)\(K\)\(j\)\(E\)\(k\)\(Y\),转换了 \(l\) 次时的可能性。

转移方程详见代码,时间复杂度 \(O(n^5)\)\(K\) 超过 \(\frac{sz(sz-1)}{2}\) 就是在走倒退)。

#include<bits/stdc++.h>
#define ll long long
using namespace std;
string s;int k,n,m,y;
int a[35],b[35],c[35];
ll dp[35][35][35][605],ans;
int sm1[35],sm2[35],sm3[35];
int main(){
	ios::sync_with_stdio(0);
	cin.tie(0);cout.tie(0);
	cin>>s>>k;int sz=s.size();
	k=min(k,sz*(sz-1)/2);
	for(int i=0;s[i];i++){
		sm1[i+1]=sm1[i];
		sm2[i+1]=sm2[i];
		sm3[i+1]=sm3[i];
		if(s[i]=='K')
			a[++n]=i+1,sm1[i+1]++;
		if(s[i]=='E')
			b[++m]=i+1,sm2[i+1]++;
		if(s[i]=='Y')
			c[++y]=i+1,sm3[i+1]++;
	}dp[0][0][0][0]=1;
	for(int i=0;i<=n;i++)
		for(int j=0;j<=m;j++)
			for(int l=0;l<=y;l++)
				for(int t=0;t<=k;t++){
					if(i<n){
						int p=a[i+1],cnt=max(0,sm2[p]-j)+max(0,sm3[p]-l);
						//cnt指将第i+1个K移动到第i+j+l+1位所用的代价,下同 
						dp[i+1][j][l][t+cnt]+=dp[i][j][l][t];
					}if(j<m){
						int p=b[j+1],cnt=max(0,sm1[p]-i)+max(0,sm3[p]-l);
						dp[i][j+1][l][t+cnt]+=dp[i][j][l][t];
					}if(l<y){
						int p=c[l+1],cnt=max(0,sm1[p]-i)+max(0,sm2[p]-j);
						dp[i][j][l+1][t+cnt]+=dp[i][j][l][t];
					}if(i+j+l==sz) ans+=dp[i][j][l][t];
				}
	cout<<ans;
	return 0;
}
posted @ 2024-07-31 21:17  长安一片月_22  阅读(6)  评论(0编辑  收藏  举报