CF Trainings Season 1 Episode 6 I (dp)

本文介绍了一个有趣的问题:如何将一个包含A和B的DNA序列通过最少的操作次数转换为全A序列。提供了两种操作方式:单个字符翻转和前缀翻转,并详细展示了使用动态规划解决该问题的代码实现。
Problem I. DNA
Input le: stdin
Output le: stdout
Time limit: 2 seconds
Memory limit: 256 megabytes
Biologists have discovered a strange DNA molecule, best described as a sequence of N characters from
the set {A, B}.
An unlikely sequence of mutations has resulted in a DNA strand consisting only of A's. Biologists found
that very odd, so they began studying the mutations in greater detail.
They discovered two types of mutations. One type results in changing a single character of the sequence
(A ! B or B ! A). The second type changes a whole prex of the sequence, specically replacing all
characters in positions from 1 to K (for some K between 1 and N, inclusive) with the other character (A
with B, B with A).
Compute the least possible number of mutations that could convert the starting molecule to its end state
(containing only A characters). Mutations can occur in any order.
Input
The rst line of input contains the positive integer N (1 N 1 000 000), the length of the molecule.
The second line of input contains a string with N characters, with each character being either A or B.
This string represents the starting state of the molecule.
Output
The rst and only line of output must contain the required minimum number of mutations.
Example
stdin stdout
4
ABBA
2
5
BBABB
2
12
AAABBBAAABBB
4

Page 1

把一个只含A,B的原串变成全A的串,求最少操作数。两种操作,1,改变单个字符 2把前k个字符取反。状态dp[i][0]表示前i个字符由原串到目标串的最少操作,dp[i][1]表示前i个字符由原串取反的串到目标串的最少操作。

#include <iostream>
#include <cstring>
#include <cstdio>
#include <string>
#include <algorithm>
#include <map>
#include <vector>
#include <queue>
#include <set>
#include <cmath>
using namespace std;
typedef long long LL;
typedef pair<int,int> P;
const int maxn = 1000000 + 5;
const int INF = 1000000000;

string s1;
int dp[maxn][2];

int main(){
    int n;
    while(scanf("%d",&n) != EOF){
        cin >> s1;
        if(s1[0] == 'A'){
            dp[0][0] = 0;
            dp[0][1] = 1;
        }
        else{
            dp[0][1] = 0;
            dp[0][0] = 1;
        }
        for(int i = 1;i < n;i++){
            if(s1[i] == 'A'){
                dp[i][0] = dp[i-1][0];
                dp[i][1] = min(dp[i-1][0]+1,dp[i-1][1]+1);
            }
            else{
                dp[i][0] = min(dp[i-1][1]+1,dp[i-1][0]+1);
                dp[i][1] = dp[i-1][1];
            }
        }
        printf("%d\n",dp[n-1][0]);
    }
    return 0;
}


评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值