MZOJ #68 基因重组

题目

分析

 part 1

关于这道题,我一直以为切下来的DNA片段可以存起来,可以备用(那这还怎么DP?!)。

我一直以为insert的必须来自原料串

于是这道题好难好难(……)

后来教练告诉我不能存起来

后来教练告诉我insert的不来自原料串

笑容逐渐凝固

我真傻,真的

part 2

这道题最大的难点在理解题意上

这道题的难点大概就在状态表示与初始化了

状态确定后,方程就好找了

关于状态,因为copy与cut都可以连续,所以必须存入上一次是否是copy或cut便于连续;

copy可以翻转,这个也要存下来

当然还要存下当前的最优方案

于是状态:

dp[i][j][0/1/2/3]表示用了原料串的前i个,目标串拼完了第j个的最优方案

1:表示最后一步为copy且不翻转的最优方案

2:表示最后一步为copy且要翻转的最优方案

3:表示最后一步为cut的最优方案

0:表示最优方案(对最后一步无限制)

part 3

状态确定,方程就好写了:

if(t[j] == s[i]) dp[i][j][1] = min(dp[i-1][j-1][1],dp[i-1][j-1][0]+c1);

if(t[j] == match(s[i])) dp[i][j][2] = min(dp[i-1][j-1][2],dp[i-1][j-1][0]+c1);

dp[i][j][3] = min(dp[i-1][j][3],dp[i-1][j][0]+c2);

dp[i][j][0] = min(dp[i][j][1],min(dp[i][j][2],dp[i][j][3]));

dp[i][j][0] = min(dp[i][j][0],dp[i][j-1][0]+c3);

part 4

O(n2)的复杂度会爆空间,看方程,当前dp[i][][]只与dp[i-1][][]有关,所以滚动i就好

题解:

代码

  1 /***************************
  2 User:Mandy.H.Y
  3 Language:c++
  4 Problem:DNA
  5 Algorithm:
  6 Score:
  7 ***************************/
  8 
  9 //注意边界!!! 
 10 
 11 /*
 12 
 13 D[i,j]表示原材料已经去掉了前i个,目标链已经生成了前j个所需的最小花费。
 14 
 15 d[i,j,0]表示使用任意方法达到状态D[i,j]的最少时间,d[i,j,1]与d[i,j,2]表示最后一
 16 次使用正向与反向切割拷贝的方法达到状态D[i,j]的最少时间,d[i,j,3]表示最后一次使用删
 17 除原串的方法达到状态D[i,j]的最少时间。
 18 
 19 
 20 */
 21 
 22 #include<bits/stdc++.h>
 23 
 24 using namespace std;
 25 
 26 const int maxn = 5005;
 27 const int maxt = 20000;
 28 
 29 int c1,c2,c3,sl,tl;
 30 char s[maxn];
 31 char t[maxn];
 32 int dp[3][maxn][5];
 33 
 34 template<class T>inline void read(T &x){
 35     x = 0;bool flag = 0;char ch = getchar();
 36     while(!isdigit(ch)) flag |= ch == '-',ch = getchar();
 37     while(isdigit(ch)) x = (x << 1) + (x << 3) + (ch ^ 48),ch = getchar();
 38     if(flag) x = -x;
 39 }
 40 
 41 template<class T>void putch(const T x){
 42     if(x > 9) putch(x / 10);
 43     putchar(x % 10 | 48);
 44 }
 45 
 46 template<class T>void put(const T x){
 47     if(x < 0) putchar('-'),putch(-x);
 48     else putch(x);
 49 }
 50 
 51 void file(){
 52     freopen("DNA.in","r",stdin);
 53     freopen("DNA.out","w",stdout);
 54 }
 55 
 56 void readdata(){
 57     read(c1);read(c2);read(c3);
 58     scanf("%s",s);sl = strlen(s);
 59     scanf("%s",t);tl = strlen(t);
 60 } 
 61 
 62 char match(char a){
 63     if(a == 'T') return 'A';
 64     if(a == 'A') return 'T';
 65     if(a == 'C') return 'G';
 66     if(a == 'G') return 'C';
 67 }
 68 
 69 void work(){
 70     memset(dp,0x3f3f3f3f,sizeof(dp));
 71     dp[0][0][0] = 0;
 72     dp[0][0][3] = c2;//初始化 
 73     int cur = 0;
 74     int ans = 2e9;
 75     
 76     for(int i = 1;i <= tl ; ++ i){
 77         dp[0][i][0] = dp[0][i-1][0]+c3;//不用材料串 
 78     }
 79     ans = dp[0][tl][0];
 80     cur = 1;
 81     for(int i = 0;i < sl; ++ i){
 82         
 83         dp[cur][0][3] = c2;
 84         dp[cur][0][1] = 0x3f3f3f3f;
 85         dp[cur][0][2] = 0x3f3f3f3f;
 86         dp[cur][0][3] = 0x3f3f3f3f;
 87         dp[cur][0][0] = c2;//%%% 
 88         //只删原料串 
 89         for(int j = 1;j <= tl; ++ j){//把j右移一位,便于处理边界 
 90             
 91             dp[cur][j][1] = 0x3f3f3f3f;
 92             dp[cur][j][2] = 0x3f3f3f3f;
 93             dp[cur][j][3] = 0x3f3f3f3f;//初始化 !!! 
 94             
 95             if(t[j-1] == s[i]) dp[cur][j][1] = min(dp[cur^1][j-1][1],dp[cur^1][j-1][0]+c1);
 96             
 97             if(t[j-1] == match(s[i])) dp[cur][j][2] = min(dp[cur^1][j-1][2],dp[cur^1][j-1][0]+c1);
 98             
 99             dp[cur][j][3] = min(dp[cur^1][j][3],dp[cur^1][j][0]+c2);
100             
101             dp[cur][j][0] = min(dp[cur][j][1],min(dp[cur][j][2],dp[cur][j][3]));
102             
103             dp[cur][j][0] = min(dp[cur][j][0],dp[cur][j-1][0]+c3);
104             
105         }
106         ans = min(ans,dp[cur][tl][0]);
107         cur ^= 1;
108     }
109     put(ans);
110 }
111 
112 int main(){
113 //    file();
114     readdata();
115     work();
116     return 0;
117 }
View Code
非做顽石不可,哪管他敬仰暗唾
原文地址:https://www.cnblogs.com/Mandy-H-Y/p/11410740.html