题目:dd爱科学1.0
Description
大科学家dddd最近在研究转基因白菜,白菜的基因序列由一串大写英文字母构成,dddd经过严谨的推理证明发现,只有当白菜的基因序列呈按位非递减形式时,这株白菜的高附加值将达到最高,于是优秀的dddd开始着手修改白菜的基因序列,dddd每次修改基因序列的任意位需要的代价是11,dddd想知道,修改白菜的基因序列使其高附加值达到最高,所需要的最小代价的是多少。
Input
第一行一个正整数n(1≤n≤1000000)
第二行一个长度为n的字符串,表示所给白菜的基因序列
保证给出字符串中有且仅有大写英文字母
Output
输出一行,表示最小代价
Sample
输入
5
ACEBF
输出
1
说明
改成ACEEF或者ACEFF,都只用改动一个字符,所需代价最小为1
Solution
1、变相的求最长非递减子序列长度。数据范围较大,显然O(n2)的时间复杂度无法通过,使用二分法可将时间复杂度降到O(nlogn)。
2、dp也可以求解,dp[i][j] 表示第i个字符变为字母j需要的最小代价。(1<=i<=n,0<=j<26)
其中dp[i][j] = min(dp[i-1][0],dp[i-1][1],…,dp[i-1][25]) + (s[i] - ‘A’ != j)
AC Code
#include<bits/stdc++.h>
using namespace std;
int n;
string s;
int r[1000010];
int len = 1;
int main(){
cin>>n;
cin>>s;
r[1] = s[0] - 'A';
for(int i = 1; i < n ;i++){
int pos = upper_bound(r + 1, r + len + 1, s[i] - 'A') - r;
r[pos] = s[i] - 'A';
len = max(len, pos);
}
cout<<n - len<<endl;
return 0;
}
#include<bits/stdc++.h>
using namespace std;
int n;
string s;
int dp[1000010][26];
int main(){
cin>>n;
cin>>s;
for(int i = 0; i <= n ; i++){
for(int j = 0; j < 26; j++){
dp[i][j] = 10000000;
}
}
for(int i = 0; i < 26; i++){
if(s[0]-'A' == i) dp[0][i] = 0;
else dp[0][i] = 1;
}
for(int i = 1; i < n; i++){
for(int j = 0; j < 26; j++){
for(int k = 0; k <= j; k++){
dp[i][j] = min(dp[i][j],dp[i-1][k]);
}
if(s[i] - 'A' != j) dp[i][j] ++;
}
}
int ans = 10000000;
for(int i = 0; i < 26; i++){
ans = min(ans,dp[n-1][i]);
}
cout<<ans<<endl;
return 0;
}