E. Keyboard Purchase 题解(状压dp+思维) ##
题目链接
题目思路
这个题目看数据范围就是一个状压dp
但是如何设置有点巧妙,因为你不知道已经放入字母的位置
所以就类似贡献的思维来搞
这个感觉有点说不清楚。。。
代码
#include<bits/stdc++.h>
#define fi first
#define se second
#define debug cout<<"I AM HERE"<<endl;
using namespace std;
typedef long long ll;
const int maxn=1e5+5,inf=0x3f3f3f3f;
const double eps=1e-6;
int n,m;
char s[maxn];
int num[30][30];
ll dp[(1<<20)+5];
signed main(){
scanf("%d%d %s",&n,&m,s+1);
for(int i=1;i<n;i++){
num[s[i]-'a'][s[i+1]-'a']++;
num[s[i+1]-'a'][s[i]-'a']++;
}
memset(dp,0x3f,sizeof(dp));
dp[0]=0;
for(int i=0;i<(1<<m);i++){
ll temp=0;
for(int j=0;j<m;j++){// 有
if(!(i&(1<<j))) continue;
for(int k=0;k<m;k++){// 没有
if(i&(1<<k)) continue;
temp+=num[j][k];
}
}
for(int j=0;j<m;j++){
if(!(i&(1<<j))){
dp[i|(1<<j)]=min(dp[i|(1<<j)],dp[i]+temp);
}
}
}
printf("%lld\n",dp[(1<<m)-1]);
return 0;
}
不摆烂了,写题