POJ 1795 DNA Laboratory

题意:

给n个由A C T G组成的字符串。

要求用这些字符串拼接,(如果两个穿的前缀和后缀有相同的部分可以重合),要求拼接成的串

长度最短且字典序最小。

 

一直觉得是什么“字符串不会做系列”的难题,结果是一道状压DP+dfs

看到n=15这么灵性的数字应该要灵性一下的。。。

二进制状压一下

dp[state][j] 表示在state状态下,最前面的串是j的情况

然后需要预处理一下两个串拼接的时候增加的长度

dist[i][j] 表示把第i个串拼在第j个串前面增加的长度:也就是i串的长度减去i的后缀和j的前缀重合的长度

对于dfs回溯

在得到短长度,并且字典序在当前最小时,最前面的串j时,需要找第二个串,已经知道dp[all-state[j]][j]

那么枚举转移过来的情况 找到满足dp值满足,并且拼接后字典序最小的(注意这里是要去拼接比较一下,因为直接比较可能把前缀就隐藏了,不是直接比较下一个串的字典序)

易错,还有一点在输入串后,要办能够直接有完全重合的串处理掉。

 

  1 #include <stdio.h>
  2 #include <string.h>
  3 #include <iostream>
  4 #include <queue>
  5 #include <vector>
  6 #include <algorithm>
  7 #include <stack>
  8 #include <set>
  9 #include <map>
 10 #include <math.h>
 11 #define pb push_back
 12 #define CLR(a) memset(a, 0, sizeof(a));
 13 #define MEM(a, b) memset(a, b, sizeof(a));
 14 #define fi first
 15 #define se second
 16 
 17 using namespace std;
 18 
 19 typedef long long ll;
 20 
 21 const int MAXN = 107;
 22 const int MAXV = 207;
 23 const int MAXE = 207;
 24 const int INF = 0x3f3f3f3f;
 25 
 26 int sz;
 27 char s[MAXN << 1][MAXN];
 28 char str[MAXN << 1][MAXN];
 29 int n;
 30 int state[27];
 31 int dp[67000 << 1][27];
 32 int dist[27][27];
 33 char anstr[MAXN*MAXN << 1];
 34 void deal()
 35 {
 36     for (int i = 0; i < sz; i++)
 37     {
 38         for (int j = 0; j < sz; j++)
 39         {
 40             if (i == j) continue;
 41             int len = min(strlen(s[i]), strlen(s[j]));
 42             for (int l = len; l >= 0; l--)
 43             {
 44                 char ss[MAXN];
 45                 strcpy(ss, s[j]);
 46                 ss[l] = '\0';
 47                 //if (i == 0 && j == 1) cout << l << " : " << s[i]+(strlen(s[i])-l) << " " << ss << endl;
 48                 if (strcmp(s[i]+(strlen(s[i])-l), ss) == 0) 
 49                 {
 50                     dist[i][j] = strlen(s[i]) - l;
 51                     break;
 52                 }
 53             }
 54         }
 55     }
 56 }
 57 
 58 int all;
 59 void dfs(int crt, int pre)
 60 {
 61     if (crt == 0) return;
 62     int tmp = INF;
 63     int now = -1;
 64     char ts1[MAXN*MAXN], ts2[MAXN*MAXN];
 65     bool have = false;
 66     strcpy(ts1, anstr);
 67     for (int i = 0; i < sz; i++)
 68     {
 69         if (crt & state[i])
 70         {
 71             if (dp[crt+state[pre]][pre] == dp[crt][i] + dist[pre][i]) 
 72             {
 73                 if (!have)
 74                 {
 75                     now = i;
 76                     have = 1;
 77                     int d = strlen(s[pre]) -  dist[pre][now];
 78                     strcat(ts1, s[now]+d);
 79                 }
 80                 else 
 81                 {
 82                     strcpy(ts2, anstr);
 83                     int d = strlen(s[pre]) -  dist[pre][i];
 84                     strcat(ts2, s[i]+d);
 85                     if (strcmp(ts2, ts1) < 0)
 86                     {
 87                         now = i;
 88                         strcpy(ts1, ts2); 
 89                     }
 90                 }
 91             }
 92         }
 93     }
 94     strcpy(anstr, ts1);
 95     dfs(crt - state[now], now);
 96 }
 97 int main()
 98 {
 99     state[0] = 1;
100     for (int i = 1; i <= 16; i++) state[i] = state[i-1] << 1;
101     int T;
102     scanf("%d", &T);
103     for (int cas = 1; cas <= T; cas++)
104     {
105         sz = 0;
106         scanf("%d", &n);
107         for (int i = 0; i < n; i++) scanf("%s", str[i]);
108         for (int i = 0; i < n; i++)
109         {    
110             bool flag = true;
111             for (int j = 0; j < n; j++)
112             {
113                 if (i == j) continue;
114                 if (strstr(str[j], str[i]))
115                 {
116                     flag = false;
117                     break;
118                 }
119             }
120             if (flag) strcpy(s[sz++], str[i]);
121         }
122         printf("Scenario #%d:\n", cas);
123         if (sz == 0)
124         {
125             cout << str[0] << endl << endl;
126             continue;
127         }
128         if (sz == 1) 
129         {
130             cout << s[0] << endl << endl;
131             continue;
132         }
133         deal();
134         all = state[sz] - 1;
135         MEM(dp, 0x3f);
136         for (int i = 0; i < sz; i++) dp[state[i]][i] = strlen(s[i]);
137         for (int i = 0; i <= all; i++)
138         {
139             for (int j = 0; j < sz; j++)
140             {
141                 if (dp[i][j] == INF) continue;
142                 for (int k = 0; k < sz; k++)
143                 {
144                     if (state[k] & i) continue;
145                     dp[i+state[k]][k] = min(dp[i+state[k]][k], dp[i][j]+dist[k][j]);
146                 }
147             }
148         }
149         int ans = INF;
150         int now = -1;
151         for (int i = 0; i < sz; i++)
152         {
153             if (ans > dp[all][i]) 
154             {
155                 ans = dp[all][i];
156                 strcpy(anstr, s[i]);
157                 now = i;
158             }
159             else if (ans == dp[all][i] && strcmp(s[i], anstr) < 0) 
160             {
161                 strcpy(anstr, s[i]);
162                 now = i;
163             }
164         }
165         dfs(all-state[now], now);
166         cout << anstr << endl << endl;
167     }
168     return 0;
169 }

 

posted @ 2017-09-30 16:14  Lorazepam  阅读(362)  评论(0编辑  收藏  举报