• POJ 1795


    DNA Laboratory
    Time Limit: 5000MS   Memory Limit: 30000K
    Total Submissions: 1425   Accepted: 280

    Description

    Background
    Having started to build his own DNA lab just recently, the evil doctor Frankenstein is not quite up to date yet. He wants to extract his DNA, enhance it somewhat and clone himself. He has already figured out how to extract DNA from some of his blood cells, but unfortunately reading off the DNA sequence means breaking the DNA into a number of short pieces and analyzing those first. Frankenstein has not quite understood how to put the pieces together to recover the original sequence.
    His pragmatic approach to the problem is to sneak into university and to kidnap a number of smart looking students. Not surprisingly, you are one of them, so you would better come up with a solution pretty fast.
    Problem
    You are given a list of strings over the alphabet A (for adenine), C (cytosine), G (guanine), and T (thymine),and your task is to find the shortest string (which is typically not listed) that contains all given strings as substrings.
    If there are several such strings of shortest length, find the smallest in alphabetical/lexicographical order.

    Input

    The first line contains the number of scenarios.
    For each scenario, the first line contains the number n of strings with 1 <= n <= 15. Then these strings with 1 <= length <= 100 follow, one on each line, and they consist of the letters "A", "C", "G", and "T" only.

    Output

    The output for every scenario begins with a line containing "Scenario #i:", where i is the number of the scenario starting at 1. Then print a single line containing the shortest (and smallest) string as described above. Terminate the output for the scenario with a blank line.

    Sample Input

    1
    2
    TGCACA
    CAT

    Sample Output

    Scenario #1:
    TGCACAT
    

    Source

    TUD Programming Contest 2004, Darmstadt, Germany
     
     
    好恶心的状态dp啊!!!!
    首先对消除能被其他串包含的串,然后对剩下的串进行建边,建一个有向图,长度是位于一个边指向的反方向所对应的串的后缀与边指向的串的相同的最大前缀长度的负数。
    设dp[v][s] 是以v为终点,已经访问过集合s所对应的点的最小值,可建立如下方程
    dp[v][s] = min(dp[u ][s | (1 << u)] + dis[v][u])       !((1 << u) & s) = = 1
     
      1 #include <iostream>
      2 #include <cstdio>
      3 #include <cstring>
      4 #include <algorithm>
      5 using namespace std;
      6 
      7 #define maxn 105
      8 
      9 #define INF 10000
     10 
     11 int n,ca,len,sum;
     12 char s[20][maxn];
     13 int dp[20][(1 << 15) + 5],dis[20][20];
     14 bool vis[20],done[20];
     15 string ans;
     16 
     17 int cal(int x,int y) {
     18         int  _max = 0;
     19         for(int i = 0; i < strlen(s[x]); i++) {
     20                 if(s[x][i] != s[y][0]) continue;
     21                 int j,k;
     22                 for( j = i,k = 0; j < strlen(s[x]) && k < strlen(s[y]); j++,k++) {
     23                         if(s[x][j] != s[y][k]) break;
     24                 }
     25                 if(k == strlen(s[y])) {
     26                         done[y] = 1;
     27                         break;
     28                 }
     29                 if(j == strlen(s[x])) {
     30                         _max = max(_max,j - i);
     31 
     32                 }
     33         }
     34 
     35 
     36         return -_max;
     37 }
     38 void init() {
     39     for(int u = 0; u < n; u++) {
     40             if(done[u]) continue;
     41             for(int v = 0; v < n; v++) {
     42                     if(u == v || done[v]) continue;
     43                     dis[u][v] = cal(u,v);
     44 
     45 
     46             }
     47     }
     48 
     49 
     50 }
     51 
     52 void dfs(int v,int s1) {
     53         vis[v] = 1;
     54         int id = -1;
     55         string t("z");
     56         for(int u = 0; u < n; u++) {
     57                 if(done[u] || vis[u]) continue;
     58 
     59                 if(dp[v][s1] == dp[u][s1 | (1 << u)] + dis[v][u]) {
     60                         string t1(s[u] - dis[v][u],s[u] + strlen(s[u]));
     61                         if(t > t1) {
     62                                 t = t1;
     63                                 id = u;
     64                         }
     65                 }
     66 
     67 
     68         }
     69 
     70         if(id != -1) {
     71                 ans = ans + t;
     72                 dfs(id,s1 | (1 << id));
     73 
     74         }
     75 }
     76 
     77 
     78 
     79 
     80 
     81 void solve() {
     82     init();
     83 
     84     for(int s1 = (1 << n) - 2; s1; s1--) {
     85             for(int v = 0; v < n; v++) {
     86                     if(!(s1 & (1 << v)) || done[v]) continue;
     87                     for(int u = 0; u < n; u++) {
     88                             if(u == v || (s1 & (1 << u)) || done[v] ) continue;
     89                             dp[v][s1] = min(dp[v][s1],dp[u][s1 | (1 << u)] + dis[v][u]);
     90 
     91                     }
     92             }
     93     }
     94 
     95     int _min = 0;
     96     for(int i = 0; i < n; i++) {
     97             if(done[i]) continue;
     98             _min = min(_min,dp[i][1 << i]);
     99     }
    100 
    101     memset(vis,0,sizeof(vis));
    102 
    103     ans = "z";
    104     int id;
    105     for(int i = 0; i < n; i++) {
    106             if(done[i]) continue;
    107             string t(s[i]);
    108             if(dp[i][1 << i] == _min && ans > t) {
    109                     ans = t;
    110                     id = i;
    111             }
    112     }
    113 
    114     dfs(id,1 << id);
    115 
    116     printf("Scenario #%d:
    ",ca++);
    117     cout << ans << endl;
    118 
    119 
    120 
    121 }
    122 int main()
    123 {
    124     int t;
    125     //freopen("sw.in","r",stdin);
    126     scanf("%d",&t);
    127     ca = 1;
    128 
    129     while(t--) {
    130             memset(done,0,sizeof(done));
    131 
    132             scanf("%d",&n);
    133 
    134             for(int i = 0; i < n; i++) {
    135                     scanf("%s",s[i]);
    136             }
    137 
    138             memset(dis,0,sizeof(dis));
    139 
    140             for(int i = 0; i < n; i++) {
    141                     for(int s = 0; s < (1 << n); s++) {
    142                             dp[i][s] = 0;
    143                     }
    144             }
    145 
    146             solve();
    147             printf("
    ");
    148 
    149     }
    150 
    151     return 0;
    152 }
    View Code
  • 相关阅读:
    win10设置自带的ubuntu
    C语言动态分配内存及回收
    Qt编写安防视频监控系统47-基本设置
    关于Qt选择qml还是widget的深度思考
    Oracle,查询表空间所有表、表所在的表空间、用户默认表空间,以及如何缩小表空间
    Spring入门小结:HelloWorld程序、依赖注入、Bean的实例化、Bean的作用域、Bean的生命周期、Bean的装配方式
    UltraEdit,Java代码中文乱码问题的解决(包括ANSI编码,以及UTF-8编码的Java源文件)
    MyEclipse,Java代码出现中文乱码问题的解决;以及ASCII/GB2312/GBK文件格式转换为UTF-8文件格式的程序
    按键精灵的几个常见操作:激活窗口/读取Excel/FindPic/组合键输入/等待用户输入/拷贝剪贴板/等待网站返回/读写文本/统计运行时间
    Oracle导入(impdp)比较大的数据,包括创建表空间、创建用户、导入数据等;含expdp及其它
  • 原文地址:https://www.cnblogs.com/hyxsolitude/p/3589878.html
Copyright © 2020-2023  润新知