zoukankan      html  css  js  c++  java
  • POJ 3691 DNA repair

    POJ_3691

        这个题目可以直接在生成的trie图的“安全部分”进行dp,用f[i][j]表示第i步走到第j个节点时,最少repair了几个基因。

        具体的建立trie图的思想可以参考《Trie图的构建、活用与改进》这篇文章。

    #include<stdio.h>
    #include<string.h>
    #define MAXD 1010
    #define INF 0x3f3f3f3f
    char gene[MAXD], b[30];
    int f[MAXD][MAXD], next[MAXD][4], flag[MAXD], N, e, P[MAXD], q[MAXD];
    void add(int cur, int k)
    {
    ++ e;
    flag[e] = 0;
    memset(next[e], 0, sizeof(next[e]));
    next[cur][k] = e;
    }
    void init()
    {
    int i, j, k, cur;
    e = 0;
    flag[e] = 0;
    memset(next[e], 0, sizeof(next[e]));
    for(i = 0; i < N; i ++)
    {
    scanf("%s", b);
    cur = 0;
    for(j = 0; b[j]; j ++)
    {
    switch(b[j])
    {
    case 'A' : {k = 0; break;}
    case 'T' : {k = 1; break;}
    case 'C' : {k = 2; break;}
    case 'G' : {k = 3; break;}
    }
    if(!next[cur][k])
    add(cur, k);
    cur = next[cur][k];
    }
    flag[cur] = 1;
    }
    for(i = 0; i < 4; i ++)
    if(!next[0][i])
    add(0, i);
    scanf("%s", gene);
    }
    void solve()
    {
    int i, j, k, u, v, front, rear, ans;
    front = rear = P[0] = 0;
    q[rear ++] = 0;
    while(front < rear)
    {
    u = q[front ++];
    for(i = 0; i < 4; i ++)
    {
    j = next[u][i];
    if(j != 0)
    {
    q[rear ++] = j;
    if(u == 0)
    P[j] = 0;
    else
    {
    for(k = P[u]; k != 0; k = P[k])
    if(next[k][i])
    break;
    P[j] = next[k][i];
    if(flag[P[j]])
    flag[j] = 1;
    }
    }
    else
    {
    for(k = P[u]; k != 0; k = P[k])
    if(next[k][i])
    break;
    next[u][i] = next[k][i];
    }
    }
    }
    memset(f, 0x3f, sizeof(f));
    f[0][0] = 0;
    for(i = 0; gene[i]; i ++)
    {
    switch(gene[i])
    {
    case 'A' : {k = 0; break;}
    case 'T' : {k = 1; break;}
    case 'C' : {k = 2; break;}
    case 'G' : {k = 3; break;}
    }
    for(u = 0; u <= e; u ++)
    if(f[i][u] != INF)
    {
    for(j = 0; j < 4; j ++)
    {
    v = next[u][j];
    if(!flag[v])
    {
    if(j == k)
    {
    if(f[i][u] < f[i + 1][v])
    f[i + 1][v] = f[i][u];
    }
    else
    {
    if(f[i][u] + 1 < f[i + 1][v])
    f[i + 1][v] = f[i][u] + 1;
    }
    }
    }
    }
    }
    ans = INF;
    for(j = 0; j <= e; j ++)
    if(f[i][j] < ans)
    ans = f[i][j];
    printf("%d\n", ans == INF ? -1 : ans);
    }
    int main()
    {
    int t = 0;
    for(;;)
    {
    scanf("%d", &N);
    if(!N)
    break;
    printf("Case %d: ", ++ t);
    init();
    solve();
    }
    return 0;
    }


  • 相关阅读:
    浅谈MySQL字符集
    思维导图_Python知识点
    思维导图_Linux文件系统及常用监控命令
    思维导图_Linux中的软件安装命令
    思维导图_Linux中的重要日志文件
    思维导图_Linux开机启动流程
    CentOS7.6中mysql实践
    搭建集群架构
    LNMP架构
    Day004_Linux基础_基础命令之tar打包解包
  • 原文地址:https://www.cnblogs.com/staginner/p/2330673.html
Copyright © 2011-2022 走看看