CF798B 1300*

题意

解析

官方解法dp
f[i][j] 代表选到第i个字符串,全都和第i个字符串以j为首开始的部分一样的最小代价
f[i][j] = min(f[i][j],f[i-1][k]+j) (条件是第i-1个字符从k开始的部分和第i个字符串从j开始的部分相同)
答案为f[n][i]里的最小值

第一个字符串有不同种变化,剩下的字符串最终一定要和它某种变化长得一样,全都相同的时侯更新最小值
第一维第1个字符串的不同变化,第二维枚举剩下所有的字符串,第三维枚举剩下的字符串从变化几次开始,第四维判断第1个字符串和第i个字符串是否每一位都一样

代码

//dp O(N*len^3)
#include<bits/stdc++.h>
using namespace std;
const int N = 55;
int n,m,f[N][N];
string s[N];
int main(){
	cin >> n;
	for(int i=1;i<=n;i++){
		cin >> s[i];
		if(i == 1) m = s[1].size();
		s[i] = s[i] + s[i];
	} 
	memset(f,0x3f,sizeof f); 
	for(int i=1;i<=m;i++)
		f[1][i] = i - 1;
	for(int i=2;i<=n;i++)
		for(int j=1;j<=m;j++)
			for(int k=1;k<=m;k++)
				if(s[i].substr(j-1,m) == s[i-1].substr(k-1,m))
					f[i][j] = min(f[i][j],f[i-1][k] + j - 1);
	int ans = 0x3f3f3f3f;
	for(int i=1;i<=m;i++)
		ans = min(ans,f[n][i]);
	if(ans == 0x3f3f3f3f) cout << -1;
	else cout << ans;
	return 0;
}
//模拟 O(N*len^3)
int find(int t,int w){
	rep(i,0,m-1){
		int pf=1;
		rep(j,1,m)
			if(str[t][i+j]!=str[1][w+j]){
				pf=0;
				break;
			}
		if(pf)return i;
	}
	return 1000000;
}
int main(){
//	freopen("1.in","r",stdin);
	n=read();
	rep(i,1,n){
		scanf("%s",str[i]+1);
		len[i]=strlen(str[i]+1);
		rep(j,1,len[i])str[i][len[i]+j]=str[i][j];
	}
	rep(i,2,n)
		if(len[i]!=len[1]){
			puts("-1");
			return 0;
		}
	m=len[1];
	int ans=1000000000;
	rep(i,0,m-1){
		int tot=i;
		rep(j,2,n)
			tot+=find(j,i);
		ans=min(ans,tot);
	}
	if(ans<10000)cout<<ans<<endl;
	else cout<<-1<<endl;
        return 0;
}
posted @   Isaac233  阅读(18)  评论(0编辑  收藏  举报
相关博文:
阅读排行:
· 地球OL攻略 —— 某应届生求职总结
· 周边上新:园子的第一款马克杯温暖上架
· Open-Sora 2.0 重磅开源!
· 提示词工程——AI应用必不可少的技术
· .NET周刊【3月第1期 2025-03-02】
点击右上角即可分享
微信分享提示