题目
分析
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 }