题解:P13469 [GCJ 2008 #2] PermRLE
考虑 dp。
发现我们只关心相邻两个的关系,而且
如果对于
这个东西可以预处理出来。
然后还要考虑跨段的贡献,我们需要知道
考虑状压 DP 的定义:
答案是:
那么转移的话,只需要枚举下一个
#include<bits/stdc++.h>
using namespace std;
#define int long long
int n,k;
int cnt;
string s;
int f[650005][16][16];
int g[25][25];
int w[25][25];
inline void solve(){
cin>>k>>s;
n=s.size();
cnt=n/k;
memset(g,0,sizeof(g));
memset(w,0,sizeof(w));
for (int S=0;S<k;S++){
for (int T=0;T<k;T++){
if (S==T){
continue;
}
for (int p=0;p<cnt-1;p++){
g[S][T]+=(s[p*k+S]!=s[(p+1)*k+T]);
w[S][T]+=(s[p*k+S]!=s[p*k+T]);
}
w[S][T]+=(s[(cnt-1)*k+S]!=s[(cnt-1)*k+T]);
}
}
for (int S=0;S<(1<<k);S++){
for (int i=0;i<k;i++){
for (int j=0;j<k;j++){
f[S][i][j]=1e18;
}
}
}
for (int i=0;i<k;i++){
f[1<<i][i][i]=0;
}
for (int S=0;S<(1<<k);S++){
for (int st=0;st<k;st++){
for (int lst=0;lst<k;lst++){
if (S>>lst&1){
for (int nex=0;nex<k;nex++){
if (S>>nex&1){
continue;
}
f[S|(1<<nex)][st][nex]=min(f[S|(1<<nex)][st][nex],f[S][st][lst]+w[lst][nex]);
}
}
}
}
}
int ans=1e18;
for (int S=0;S<k;S++){
for (int T=0;T<k;T++){
ans=min(ans,f[(1<<k)-1][S][T]+g[S][T]+1);
}
}
cout<<ans<<"\n";
return;
}
int T;
signed main(){
ios::sync_with_stdio(0);
cin.tie(0);
cout.tie(0);
cin>>T;
for (int i=1;i<=T;i++){
cout<<"Case #"<<i<<": ";
solve();
}
return 0;
}