#define HAVE_STRUCT_TIMESPEC
#include<bits/stdc++.h>
using namespace std;
char s[100005];
int pos[(1<<20)+5];//pos[i]表示i=1<<j时的j
int cnt[35][35];//cnt[i][j]表示s[i]=i,s[i+1]=j的移动数量
int g[25][(1<<20)+5];//g[i][S],i不属于S表示s[i]=i,s[i+1]∈S的移动数量
int h[(1<<20)+5];//h[S]表示所有s[i]∈S,s[i+1]不属于S的移动数量
int dp[(1<<20)+5];
int main(){
ios::sync_with_stdio(false);
cin.tie(NULL);
cout.tie(NULL);
int n,m;
cin>>n>>m;
cin>>s+1;
for(int i=1;i<n;++i){
int gg=s[i]-'a';
int tt=s[i+1]-'a';
++cnt[gg][tt];
++cnt[tt][gg];
}
for(int i=0;i<m;++i)
pos[1<<i]=i;
for(int i=0;i<m;++i)
for(int j=1;j<(1<<m)-1;++j)
if(!((j>>i)&1))
g[i][j]=g[i][j-(j&-j)]+cnt[i][pos[j&-j]];//i和j不在同一集合内,g[i][j]表示在集合j中加入字母i的话会增加多少次移动
for(int i=1;i<(1<<m)-1;++i)
for(int j=0;j<m;++j)
if((i>>j)&1)
h[i]+=g[j][i^((1<<m)-1)];//j和i在同一集合内,枚举i内的所有元素j,求和得到集合i的补集中加依次入集合i中所有元素会增加多少次移动
for(int i=1;i<(1<<m);++i)
dp[i]=1e9+7;
dp[0]=0;
for(int i=0;i<(1<<m)-1;++i)//i上为1的位表明该字母在键盘上的位置已经确定,键盘上从左到右的顺序取决于dp过程中先后被加入进dp的h,随着更新最小值,从左到右顺序也被暗中替换为更小值的顺序(最左边字母进入时因为只有一个字母所以不会产生移动,它的贡献是最初的dp[i],i中只有一位1,dp[i]=0)
for(int j=0;j<m;++j)
if(!((i>>j)&1))
dp[i^(1<<j)]=min(dp[i^(1<<j)],h[i]+dp[i]);//求dp[i^(1<<j)]相当于在dp[i]已有的键盘顺序上最右端加入字母j,此时所有已经在键盘上的字母和剩下所有还不在键盘上的字母相邻的话移动距离都会增加一格,所以要加上h[i],即i上所有为1的位j的g[j][k]之和,k是i的补集也就是还不在键盘上的那些字母
//其实如果不为了复杂度降低一个m的话,可能更容易理解一些,这道题的关键在于每次向已经排列好的键盘右端加入一个新字母,此时依次将所有已经在键盘上的字母和与其相邻的所有还未在键盘上的字母个数相加,尽可能复杂度低的计算出这些集合与集合之间的相邻个数。
cout<<dp[(1<<m)-1];
return 0;
}

Educational Codeforces Round 74 (Rated for Div. 2)E(状压DP,降低一个m复杂度做法含有集合思维)的更多相关文章

  1. Educational Codeforces Round 74 (Rated for Div. 2) D. AB-string

    链接: https://codeforces.com/contest/1238/problem/D 题意: The string t1t2-tk is good if each letter of t ...

  2. Educational Codeforces Round 74 (Rated for Div. 2) C. Standard Free2play

    链接: https://codeforces.com/contest/1238/problem/C 题意: You are playing a game where your character sh ...

  3. Educational Codeforces Round 74 (Rated for Div. 2) B. Kill 'Em All

    链接: https://codeforces.com/contest/1238/problem/B 题意: Ivan plays an old action game called Heretic. ...

  4. Educational Codeforces Round 74 (Rated for Div. 2) A. Prime Subtraction

    链接: https://codeforces.com/contest/1238/problem/A 题意: You are given two integers x and y (it is guar ...

  5. Educational Codeforces Round 74 (Rated for Div. 2)

    传送门 A. Prime Subtraction 判断一下是否相差为\(1\)即可. B. Kill 'Em All 随便搞搞. C. Standard Free2play 题意: 现在有一个高度为\ ...

  6. Educational Codeforces Round 74 (Rated for Div. 2)【A,B,C【贪心】,D【正难则反的思想】】

    A. Prime Subtractiontime limit per test2 secondsmemory limit per test256 megabytesinputstandard inpu ...

  7. Educational Codeforces Round 74 (Rated for Div. 2)补题

    慢慢来. 题目册 题目 A B C D E F G 状态 √ √ √ √ × ∅ ∅ //√,×,∅ 想法 A. Prime Subtraction res tp A 题意:给定\(x,y(x> ...

  8. Educational Codeforces Round 61 (Rated for Div. 2)F(区间DP,思维,枚举)

    #include<bits/stdc++.h>typedef long long ll;const int inf=0x3f3f3f3f;using namespace std;char ...

  9. Educational Codeforces Round 76 (Rated for Div. 2) E. The Contest dp

    E. The Contest A team of three programmers is going to play a contest. The contest consists of

随机推荐

  1. Java代码如何关联Hadoop源码

    昨天在学习Hadoop的时候,遇到一个问题就是Java关联Hadoop源码的时候死活关联不上,但是我发现在公司的电脑就可以顺利关联到源码.考虑了一下觉得应该是Eclipse版本的问题,于是我下载了ec ...

  2. java 中使用logback日志,并实现日志按天分类压缩保存。

    以maven项目作为构建工具为例,首先引入使用logback需要的3个依赖,需要注意使用logback是需要引入slf4j-api的,因为logback是基于slf4j的 <!--logback ...

  3. AcWing 859. Kruskal算法求最小生成树 稠密图

    //稠密图 #include <cstring> #include <iostream> #include <algorithm> using namespace ...

  4. 如何使用 idea提交svn代码

    链接:https://jingyan.baidu.com/article/b2c186c80d81b1c46ff6ff59.html

  5. 关于mybatis中sql映射文件模糊查询的使用

    1.从前台传递一个String类型的参数到后台进行查询,如果牵涉到模糊查询会报错,应该把参数封装到对象中再进行传递然后进行模糊查询 2.一个查询框,多个查询条件 <if test="c ...

  6. 前端——语言——Core JS——《The good part》读书笔记——第三章节(Object)

    本章介绍对象. 在学习Java时,对象理解为公共事物的抽象,实例为具体的个例,对象为抽象的概念,例如人为抽象的概念,具体的个例为张三,李四. Java对象种类多,包含普通类,JavaBean,注解,枚 ...

  7. Chinese Window Lattice And CSS

    谁向云端着此亭,檐前树木映窗棂.-- 释绍嵩<陪赵知府登桃岭山亭> (image from 中国窗棂) The traditional Chinese window lattice has ...

  8. Go键盘输入和打印输出

    package main import ( "fmt" "bufio" "os" ) func main() { /* 输入和输出: fmt ...

  9. JS-内置对象和方法

    1.Array数组对象unshift( )    数组开头增加功能:给数组开头增加一个或多个 参数:一个或多个 返回值:数组的长度 原数组发生改变 shift( )        数组开头删除一项功能 ...

  10. 基于bs4库的HTML内容查找方法

    一.信息提取实例 提取HTML中所有的URL链接 思路:1)搜索到所有的<a>标签 2)解析<a>标签格式,提取href后的链接内容 >>> import r ...