[BZOJ4606][Apio2008]DNA-动态规划
来源:互联网 发布:找不到淘宝的卖家中心 编辑:程序博客网 时间:2024/05/14 06:04
[Apio2008]DNA
Description
分析如DNA序列这样的生命科学数据是计算机的一个有趣应用。从生物学的角度上说,DNA 是一种由腺嘌呤、胞嘧啶、鸟嘌呤和胸腺嘧啶这四种核苷酸组成的链式结构。这四种核苷酸分别用大写字母A、C、G、T表示。这样,一条DNA单链可以被表示为一个只含以上四种字符的字符串。我们将这样的字符串称作一个DNA序列 。
有时生物学家可能无法确定一条DNA单链中的某些核苷酸。在这种情况下,字符N将被用来表示一个不确定的核苷酸。换句话说,N可以用来表示A、C、G、T中的任何一个字符。我们称包含一个或者多个N的DNA序列为未完成序列;反之,就称作完成序列。如果一个完成序列可以通过将一个未完成序列中的每个N任意替换成A、C、G、T得到的话,就称完成序列适合这个未完成序列。举例来说,ACCCT适合ACNNT,但是AGGAT不适合。
研究者们经常按照如下方式排序四种核苷酸:A优先于C,C优先于G,G优先于T。如果一个DNA序列中的每个核苷酸都与其右边的相同或者优先,就将其归类为范式-1。举例来说,AACCGT是范式-1,但是AACGTC不是。
一般来说,一个DNA序列属于范式-j(j>1),只要它属于范式-(j-1)或者是一个范式-(j-1)和一个范式-1的连接。举例来说,AACCC、ACACC和ACACA都是范式-3,但GCACAC和ACACACA不是。
同样,研究者们按照字典序对 DNA 序列进行排序。按照这个定义,最小的属于范式-3的DNA序列是AAAAA,最大的是TTTTT。这里是另外一个例子,考虑未完成序列 ACANNCNNG。那么前7个适合这个未完成序列的DNA序列是:
ACAAACAAG
ACAAACACG
ACAAACAGG
ACAAACCAG
ACAAACCCG
ACAAACCGG
ACAAACCTG
写一个程序,找到按字典序的第R个适合给定的长度为M的未完成序列的范式-K。
Input
输入第一行包含三个由空格隔开的整数:M(1≤M≤50,000),K(1≤K≤10)和R(1≤R≤2×10^12)。
第二行包含一个长度为M的字符串,表示未完成序列。
保证适合该未完成序列的范式-K的总数不超过4×10^18
因此该数可以用C和C++中的long long类型或者Pascal中的Int64类型表示。
同时,R不会超过适合给定未完成序列的范式-K的总数。
Output
在第一行中输出第R个适合输入中的未完成序列的范式-K。
Sample Input
9 3 5
ACANNCNNG
Sample Output
ACAAACCCG
细节无数高能预警注意!!!
这是一个不难想,但较难写的DP……
咱在过了样例之后就直接A掉了呢……但是……
在样例都过不了的状态下调了好久……
(╯‵□′)╯︵┻━┻
思路:
这题看着就像钦定DP……
想象一下一棵字典树的样子,N处分叉。
然后,这题的DP就像是在这棵字典树上跑带转折这个条件的树形DP……
大概就是这个意思吧……
定义转折:|范式|-1。(因为基础是-1)
于是令f[i][j][k]表示当前要放第i个,放的是第j种核苷酸,有k个转折的方案数。
因为根据上面的比方,是在字典树上跑。(不是说真的要用字典树,这是比方)
所以,从后往前,得到递推式:
若当前位置字符与j相同或为’N’:
f[i][j][k]=sum(l=1~j-1){f[i+1][l][k+1]}+sum(l=j~4){f[i+1][l][k]}
咱还需要一个sum数组:
sum[i][j][k]=sum(l=1~k){f[i][j][l]}
最后在sum上当做字典树跑即可~
即为:
从前往后对每个位置从’A’到’T’进行询问,若r>当前sum,r-=当前sum~
否则往下走一层~
沿路记录下从何处往下,输出,完成ヾ(o◕∀◕)ノヾ~
#include<iostream>#include<cstdio>#include<cstring>#include<cstdlib>#include<algorithm>using namespace std;typedef long long ll;inline int trans(char c){ switch(c) { case 'N':return 0;break; case 'A':return 1;break; case 'C':return 2;break; case 'G':return 3;break; case 'T':return 4;break; }}inline char decode(int a){ switch(a) { case 1:return 'A';break; case 2:return 'C';break; case 3:return 'G';break; case 4:return 'T';break; }}const int M=50233;int m,k;int base[M],ans[M];ll r,f[M][5][13],sum[M][5][13];int main(){ char s[M]; scanf("%d%d%lld",&m,&k,&r); k--; scanf("%s",s); for(int i=1;i<=m;i++) base[i]=trans(s[i-1]); f[m+1][4][0]=1; for(int i=m;i>=1;i--)//pos for(int j=1;j<=4;j++)//acgt { if(!base[i] || base[i]==j) { for(int jj=1;jj<j;jj++)//last acgt for(int l=1;l<=k;l++)//turns f[i][j][l]+=f[i+1][jj][l-1]; for(int jj=j;jj<=4;jj++) for(int l=0;l<=k;l++) f[i][j][l]+=f[i+1][jj][l]; } else for(int l=0;l<=k;l++) f[i][j][l]=0; sum[i][j][0]=f[i][j][0]; for(int l=1;l<=k;l++) sum[i][j][l]=f[i][j][l]+sum[i][j][l-1]; } ans[0]=1; for(int i=1,j;i<=m;i++) { k--; for(j=1;j<=4;j++) { if(j==ans[i-1]) k++; if(sum[i][j][k]>=r) break; r-=sum[i][j][k]; } ans[i]=j; putchar(decode(j)); } putchar('\n'); return 0;}
- [BZOJ4606][Apio2008]DNA-动态规划
- [BZOJ4606][Apio2008]DNA(dp)
- APIO2008 脱氧核糖核苷酸DNA
- 动态规划——DNA
- bzoj 4606: [Apio2008]DNA 递推
- bzoj 4606: [Apio2008]DNA (DP)
- [BZOJ 4606][Apio2008]DNA:数位DP
- POJ3691 DNA repair AC自动机+动态规划
- [HDOJ 1560][Vjudge 23158] DNA sequence [动态规划+状态压缩]
- HDU 2457 DNA repair AC自动机 + 动态规划
- 动态规划-最短编辑距离变形----DNA对比问题
- 动态规划!!!动态规划!!!
- 用动态规划法求解生物信息学中DNA序列比对的问题 (交叉学科应用实验)
- 100道动态规划——28 POJ 2778 DNA Sequence AC自动机+DP+矩阵快速幂 很不错嘛
- 100道动态规划——40 CSUOJ 1889 Copying DNA 记忆化搜索 DP的感觉
- 动态规划
- 动态规划
- 动态规划
- iOS安全 --- 反编译
- Just a Hook (线段树+lazy标记)
- webpack的CommonsChunkPlugin插件
- Java 9 的 9 个特性
- 两年Java开发工作经验面试总结
- [BZOJ4606][Apio2008]DNA-动态规划
- MySQL(3)-子查询、连接、运算符及函数
- 用python实现简单爬虫
- Ajax 小 Demo 集合(一)
- Android中利用反射机制创建实例的代码
- 解读一段循环冗余校验(CRC)算法程序
- java中的session对象及其常用方法
- 数据结构——顺序表的基本操作
- SwipeRefreshLayout详解和自定义上拉加载更多