poj 1699 Best Sequence (搜索技巧 剪枝 dfs)

题目链接

题意:给出几个基因片段,要求你将它们排列成一个最短的序列,序列中使用了所有的基因片段,而且不能翻转基因。

分析:先计算出add数组,再dfs枚举。

 1 #include <iostream>
 2 #include <cstring>
 3 #include <cstdlib>
 4 #include <cmath>
 5 #include <cstdio>
 6 #include <vector>
 7 #include <algorithm>
 8 #define LL long long
 9 using namespace std;
10 const int maxn = 20+10;
11 const int INF = 1<<28;
12 int n, len[maxn], add[maxn][maxn], ans;
13 bool vis[maxn];
14 char s[maxn][maxn];
15
16 void cal(int a, int b, int lena, int lenb) //add计算串a在串b,前面增加的字符个数。
17 {
18     int i, j, k, f, x;
19     for(i = 0; i < lena; i++)
20     {
21         f = 0;
22         for(j = 0, k = i; j < lenb && k < lena; j++, k++)
23         {
24             if(s[a][k] == s[b][j]) continue;
25             else { f = 1; break; }
26         }
27         if(f == 0) break;
28     }
29     x = lena - i;
30     add[a][b] = lenb - x;
31     if(add[a][b]<0) add[a][b] = 0;
32 }
33 void dfs(int pre, int sum, int lenth) //分别代表之前的串,和串的总数,总串的长度。
34 {
35     if(lenth >= ans) return;
36     if(sum == n)
37     {
38         if(lenth < ans) ans = lenth;
39         return;
40     }
41     for(int i = 0; i < n; i++)
42     {
43       if(!vis[i])
44       {
45           vis[i] = true;
46           if(add[pre][i]==0) //一定要注意这是存在包含串,如abcdabc 包含 dab
47           //串a包含串b,等价于从a到b的边等于0,那么这时,状态在转移时,在原本
48           //是以串a结尾的状态加入串b,此时目标状态仍然是以串a结尾,这里需要注意。
49           dfs(pre, sum+1, lenth+add[pre][i]);
50           else
51           dfs(i, sum+1, lenth+add[pre][i]);
52           vis[i] = false;
53       }
54     }
55 }
56 int main()
57 {
58     int t, i, j;
59     scanf("%d", &t);
60     while(t--)
61     {
62         ans = INF;
63         memset(add, 0, sizeof(add));
64         memset(vis, false, sizeof(vis));
65         scanf("%d", &n);
66         for(i = 0; i < n; i++)
67         {
68             scanf("%s", s[i]);
69             len[i] = strlen(s[i]);
70         }
71         for(i = 0; i < n; i++)
72         for(j = 0; j < n; j++)
73         cal(i, j, len[i], len[j]);
74         for(i = 0; i < n; i++)
75         {
76             vis[i] = true;
77             dfs(i, 1, len[i]);
78             vis[i] = false;
79         }
80         printf("%d\n", ans);
81     }
82     return 0;
83 }

poj 1699 Best Sequence (搜索技巧 剪枝 dfs),布布扣,bubuko.com

时间: 2024-10-10 16:41:22

poj 1699 Best Sequence (搜索技巧 剪枝 dfs)的相关文章

POJ 1699 Best Sequence (DFS+预处理)

题意:看那张图就一清二楚了吧, N个序列首位相连(相同的序列部分),得到最短的总序列. 题目链接:http://poj.org/problem?id=1699 ~~~~ 思路就是:将N个序列首尾相连能重合的长度求粗来.然后DFS枚举每种首尾相连的情况. #include<cstdio> #include<cstring> #include<algorithm> #define N 22 #define INF 0x7fffffff using namespace std

poj 1699 Best Sequence(dfs)

http://poj.org/problem?id=1699 题意:给出n个只含A,C,G,T的字符串,要求能把这n个字符串组合起来的最短长度. 思路:预处理一下,a[i][j]表示将第j个字符串连接到第i个字符串后面增加的长度,那么我们需要找出这样一个序列1,2....n满足a[1][2] + a[2][3] + ...+a[n-1][n]的最小值.DFS就OK了,任选一个字符串作为起点进行dfs,求出所有的情况后得到最小的长度. #include <stdio.h> #include &l

POJ 1699 Best Sequence(DFS)

題目鏈接 題意 : 將幾個片段如圖所示方法縮成一個序列,求出最短這個序列. 思路 : 其實我也不知道怎麼做.....看網上都用了DP.....但是我不會.....這個DP不錯,還有用KMP+状压DP做的 1 //1699 2 #include <iostream> 3 #include <stdio.h> 4 #include <string.h> 5 #include <string> 6 7 using namespace std; 8 9 string

poj 1699 Best Sequence

http://poj.org/problem?id=1699 题意:给你n个长度为L的序列,求包含这几个序列的最短长度. 先预处理每两个序列之间的关系,然后dfs枚举就行. 1 #include <cstdio> 2 #include <cstring> 3 #include <algorithm> 4 #define maxn 500 5 using namespace std; 6 const int inf=1<<30; 7 8 char str[ma

poj 1699 Best Sequence(AC自动机+状压DP)

题目链接:poj 1699 Best Sequence 题目大意:给定N个DNA序列,问说最少多长的字符串包含所有序列. 解题思路:AC自动机+状压DP,先对字符串构造AC自动机,然后在dp[s][i]表示匹配了s,移动到节点i时候的最短步数. #include <cstdio> #include <cstring> #include <queue> #include <vector> #include <iostream> #include &

poj sticks 木棍 枚举+搜索+小技巧

这大概是我复赛前看过的题了,那个时候的我其实还不是很会打搜索,甚至认为搜索,枚举的效率都是很低的,是不能够把题AC的,后来为了改变这种看法(其实是因为我发现一些我想不出的题的AC程序里大多有搜索,枚举的算法,格外揪心,没想到竟这么简单).才做了一些搜索的题.这就是那些年曾令我揪心的题之一,想不出,去百度,这么简单,心碎了.的确搜索如果剪枝做的好的话,是可以把一些题目AC的. .   好吧!可打完后提交的第一次还是TLE了,心好累.去别人的博客园看了一下,其实大家都差不多.仔细一看才发现别人是降序

poj 1088 滑雪 【记忆化搜索】+【DFS】

策略:如题 题目链接:http://poj.org/problem?id=1088 代码: #include<stdio.h> #include<string.h> int map[105][105], dp[105][105], n, m; const int dir[4][2] = {0, 1, 1, 0, 0, -1, -1, 0}; //四个方向 int limit(int x, int y) //判断是不是越界了 { if(x<1||x>n||y<1||

poj 2965 The Pilots Brothers&#39; refrigerator 【dfs+枚举】【双十一大礼包】

The Pilots Brothers' refrigerator Time Limit: 1000MS   Memory Limit: 65536K Total Submissions: 27522   Accepted: 10625   Special Judge Description The game “The Pilots Brothers: following the stripy elephant” has a quest where a player needs to open

POJ 2386 Lake Counting 搜索题解

简单的深度搜索就可以了,看见有人说什么使用并查集,那简直是大算法小用了. 因为可以深搜而不用回溯,故此效率就是O(N*M)了. 技巧就是增加一个标志P,每次搜索到池塘,即有W字母,那么就认为搜索到一个池塘了,P值为真. 搜索过的池塘不要重复搜索,故此,每次走过的池塘都改成其他字母,如'@',或者'#',随便一个都可以. 然后8个方向搜索. #include <stdio.h> #include <vector> #include <string.h> #include