l
i
n
k
\textcolor{gray}{link}
link
分析:
将字符串分配大小后 发现若
S
i
>
=
S
i
+
1
S_i>=S_{i+1}
Si>=Si+1 在此处划分是最优的
预处理
i
i
i与
i
+
1
i+1
i+1划分的
c
o
s
t
cost
cost 预处理将
i
i
i放入排列末尾的代价
g
i
,
s
t
g_{i,st}
gi,st
于是简单状压
d
p
dp
dp处理
g
g
g和
a
n
s
ans
ans即可
CODE:
#include<iostream>
#include<cstdio>
#include<algorithm>
#include<cstring>
using namespace std;
const int N=1e5+5;
int vis[27],f[1<<20],g[27][1<<20],a[30][30],S,cnt[30];
char s[N];
int main(){
scanf("%s",s);
int len=strlen(s),tot=0;
for(int i=0;i<len;i++)
vis[s[i]-'a']=1;
for(int i=0;i<26;i++)
if(vis[i]) cnt[i]=tot++;
S=(1<<tot)-1;
for(int i=0;i<len-1;i++)
a[cnt[s[i]-'a']][cnt[s[i+1]-'a']]++; //划分代价
for(int i=0;i<tot;i++)
for(int j=0;j<tot;j++)
for(int k=(1<<j);k<=(2<<j)-1;k++)
g[i][k]=g[i][k-(1<<j)]+a[i][j];
memset(f,0x3f,sizeof f);
f[0]=0;
for(int i=0;i<=S;i++)
for(int j=0;j<tot;j++)
if(!((i>>j)&1))
f[i|1<<j]=min(f[i|1<<j],f[i]+g[j][i|1<<j]);
printf("%d",f[S]+1);
return 0;
}