bzoj4606 DNA

题意有点复杂,就自己去看吧。

 

题解   

f[i][j][k]表示第i为,为-j范式,当前位为k的方案数,从后往前dp一遍。

然后再贪心的从前往后填数。但注意当前填的数已经是-cur范式,计算方案的时候要用k-cur来算。

 

 1 #include<iostream>
 2 #include<cstdio>
 3 #include<cstring>
 4 #include<algorithm>
 5 using namespace std;
 6 #define maxn 100020
 7 
 8 typedef long long ll;
 9 ll f[maxn][11][4],R;
10 int mp[200],a[maxn],ans[maxn];
11 int n,k;
12 char ch[maxn],re[5];
13 
14 void init(){
15     if ( a[n] == 5 ){
16         for (int l = 0 ; l <= 3 ; l++){
17             for (int i = 1 ; i <= k ; i++){
18                 f[n][i][l] = 1;
19             }
20         }
21     }
22     else{
23         for (int i = 1 ; i <= k ; i++)f[n][i][a[n]] = 1; 
24     }
25     for (int i = n - 1 ; i ; i--){
26         if ( a[i] < 5 ){
27             for (int j = 1 ; j <= k ; j++){
28                 for (int l = 0 ; l <= 3 ; l++){
29                     if ( a[i] >= l ) f[i][j][a[i]] += f[i + 1][j][l]; //如果有这种转移就不能在用f[i + 1][j - 1][l]在更新了。因为f[i + 1][j][l]已经包含了它的方案数,否则会算重
30                     else f[i][j][a[i]] += f[i + 1][j - 1][l];
31                 }
32             }
33         }
34         else{
35             for (int l = 0 ; l <= 3 ; l++){
36                 for (int j = 1 ; j <= k ; j++){
37                     for (int p = 0 ; p <= 3 ; p++){
38                         if ( l >= p ) f[i][j][l] += f[i + 1][j][p];
39                         else f[i][j][l] += f[i + 1][j - 1][p];
40                     }
41                 }
42             }
43         }
44     }
45 /*    for (int i = 1 ; i <= n ; i++)
46        for (int l = 0 ; l <= 3 ; l++)    
47         for (int j = 1 ; j <= k ; j++){
48             f[i][j][l] += f[i][j - 1][l];
49         }*/
50 }
51 void solve(){
52     int cur = 1;
53     ans[0] = 5;
54     for (int i = 1 ; i <= n ; i++){
55         if ( a[i] == 5 ){
56             ll sum[4];
57             for (int l = 0 ; l <= 3 ; l++){
58                 if ( ans[i - 1] < l ) sum[l] = f[i][k - cur][l];
59                 else sum[l] = f[i][k - cur + 1][l];    
60             }
61             for (int l = 3 ; l >= 0 && R > 0 ; l--){
62                 ans[i] = l , R -= sum[l];
63             }
64             R += sum[ans[i]];
65             if ( ans[i - 1] < ans[i] ) cur++;
66         }    
67         else{
68             ans[i] = a[i];
69             if ( ans[i - 1] < ans[i] ) cur++;
70         }
71     }
72     for (int i = 1 ; i <= n ; i++) printf("%c",re[ans[i]]);
73     printf("\n");
74 }
75 int main(){
76     freopen("input.txt","r",stdin);
77     mp['A'] = 3 , mp['C'] = 2 , mp['G'] = 1 , mp['T'] = 0 , mp['N'] = 5;
78     re[3] = 'A' , re[2] = 'C' , re[1] = 'G' , re[0] = 'T';
79     scanf("%d %d %lld",&n,&k,&R);
80     scanf("%s",ch + 1);
81     for (int i = 1 ; i <= n ; i++) a[i] = mp[(int)ch[i]];
82     init();
83     solve();
84 }

 

posted @ 2016-05-24 18:38  zhangqingqi  阅读(203)  评论(0编辑  收藏  举报