@xiaoziyao
2020-10-20T19:36:12.000000Z
字数 855
阅读 948
解题报告
CF1238E Keyboard Purchase解题报告:
状压dp。
看到这么小的,我们就可以大概猜出要压这个,于是套路的设计状态:为设计的键盘(不需要设计完)用到的所有字母压缩起来是的最小缓慢度。
但是有一个问题,对于这个状态,我们不能知道它字母的顺序,所以并不能统计答案。
我们要设计一种无后效性的dp:每一次装一个字母就直接统计出来它的所有贡献(费用提前思想)。
考虑装一个字母的贡献:会让所有相邻且一个装了一个没装的字母对距离加一,这样我们就可以快速地统计出来答案了。
设为相邻的状态数,很容易统计出来,然后就是套路的状压dp了。
代码非常简短,记得开。
for(int i=1;i<n;i++)
cnt[s[i]-96][s[i+1]-96]++,cnt[s[i+1]-96][s[i]-96]++;
st=(1<<m)-1;
f[0]=0;
for(int i=1;i<=st;i++){
int sum=0;
f[i]=inf;
for(int j=1;j<=m;j++)
for(int k=j+1;k<=m;k++)//不统计重复
if(((i>>(j-1))&1)^((i>>(k-1))&1))//j在键盘上或k在键盘上
sum+=cnt[j][k];
for(int j=1;j<=m;j++)
if((i>>(j-1)&1))
f[i]=min(f[i],f[i^(1<<(j-1))]+sum);
}
printf("%lld\n",f[st]);