题目链接:题目
下面有两种解法:第一种字符串暴力 第二种dp
#include<iostream>
using namespace std;
const int maxn=60;
long long arr[maxn];
int main(void) {
int n,k,i,ans=0;
string str;
cin>>n>>k>>str;
for(int i=0;i<n;i++)
arr[str[i]-'a']=1;
int kk=0;
for(i=0;i<26;i++){
if(arr[i]==1){
ans+=(i+1);
i++;
kk++;
if(kk==k){
cout<<ans<<endl;
return 0;
}
}
}
cout<<-1<<endl;
return 0;
}
转移方程见注释
//dp[取的字符串长度(0-k闭区间)][取哪个字母(1-26闭区间)]
//状态转移方程dp[i][j]=min(dp[i][j],dp[i-1][l]+j)
#include<iostream>
#include<cstring>
using namespace std;
const int maxn=60;
const int INF=0x3f3f3f3f;
int dp[maxn][maxn],s[27];
int main(void) {
int n,k,i,m,j,l;
string str;
cin>>n>>k>>str;
for(int i=0; i<n; i++)
s[str[i]-'a'+1]=1;
memset(dp,INF,sizeof(dp));
memset(dp[0],0,sizeof(dp[0]));//i=0的预处理
for(i=1; i<=26; i++)//i=1的预处理
if(s[i])
dp[1][i]=i;
for(i=2; i<=k; i++)
for(j=1; j<=26; j++)
if(s[j]) {
for(int l=1;l<j-1;l++)//因为不能取相邻字母,所以l<j-1
dp[i][j]=min(dp[i][j],dp[i-1][l]+j);
}
int ans=INF;
for(int i=1;i<=26;i++){
ans=min(ans,dp[k][i]);
}
if(ans==INF)
cout<<-1<<endl;
else
cout<<ans<<endl;
return 0;
}