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;
}


posted @ 2021-09-30 15:13  hunxuewangzi  阅读(18)  评论(0编辑  收藏  举报