HDOJ 1560 DNA sequence 状压dp 或 IDA*

http://acm.hdu.edu.cn/showproblem.php?pid=1560

题意:

给不超过8个子串,每个子串最多5位,且都只包含ATCG,求最短的母串长度。

分析:

又是上个月写的,所以有点忘了。。正解是IDA*。然后可以状压dp,记忆化搜索。dp[i],i用6进制表示,每位表示对应的子串匹配那么多长度所需要的最短母串长度。比如两个子串,13=2*6^1+1*6^0,dp[13]就表示第一个串匹配了第一位,第二个串匹配前两位所需要的最短母串长度。

状态讲完了,不过实际上程序里是倒着做的,也就是从末尾开始匹配。转移就是枚举母串最后一位分别为ATCG,然后如果子串未匹配的最后一位相同那就匹配上了,压缩出新的六进制数继续搜下去,递归到0。dp[i] = min(dp[j] + 1)。

然后数组比较大,在网上看到一个hash标记的方法,这样就不用总是memset,速度快了1s+。

额。。找到了当时写在文档里的一点点题解,比现在回顾写得清晰一点吧。。

正解是IDA*,数据范围小可以用状压,记忆化搜索。dp[i]=min(dp[j])+1,i用六进制,每一位表示为每个子序列匹配了(0-5)的长度,母序列所需要的最小长度,转移时就是删掉ATCG中一个,判断每个子序列最后匹配的那一位是否相同(相同删掉,可能会疑惑如果不是匹配母串的当前这位怎么能也删掉,实际上贪心地看,越早匹配掉越好,就是比如dp[3 * 6 + 2]是优于(可能小于) dp[3 * 6 + 3]的),由此得到子状态j的值

 1 #include<cstdio>
 2 #include<cstring>
 3 using namespace std;
 4
 5 int n, cas;
 6 int dp[6*6*6*6*6*6*6*6 + 100],
 7     ha[6*6*6*6*6*6*6*6 + 100];
 8 char str[10][10];
 9 char ch[4] = {‘A‘, ‘T‘, ‘C‘, ‘G‘};
10 int min(int a, int b)
11 {
12     if (a < b) return a; else return b;
13 }
14 void F(int x)
15 {
16     if (ha[x] == cas) return;
17     int xx = x, p[10], op[10];
18     for (int i = n - 1; i >= 0; i--)
19     {
20         op[i] = p[i] = xx % 6;            //解码
21         xx /= 6;
22     }
23     for (int i = 0; i < 4; i++)
24     {
25         for (int j = 0; j < n; j++)
26             if (p[j] > 0 && str[j][p[j] - 1] == ch[i]) p[j] --;    //匹配上目前枚举的字符
27         int sum = 0;
28         for (int j = 0; j < n; j++)
29             sum = sum * 6 + p[j];                    //再压缩编码
30         for (int j = 0; j < n; j++)
31             p[j] = op[j];
32         if (sum == x) continue;
33         F(sum);                            //递归求解
34         //dp[x] = dp[x]==-1? dp[sum]+1: min(dp[x], dp[sum]+1);
35         if (ha[x] != cas)
36         {
37             dp[x] = dp[sum] + 1;
38             ha[x] = cas;
39         }
40         else
41         {
42             dp[x] = min(dp[sum] + 1, dp[x]);
43             //ha[x] = cas;
44         }
45     }
46 }
47 int main()
48 {
49     int T;
50     scanf("%d", &T);
51     cas = 0;
52     memset(ha, -1, sizeof(ha));
53     while (T--)
54     {
55         scanf("%d", &n); getchar();
56         //memset(dp, -1, sizeof(dp));
57         int sum = 0;
58         for (int i = 0; i < n; i++)
59         {
60             scanf("%s", str[i]);
61             sum = sum * 6 + strlen(str[i]);        //压缩编码
62         }
63         dp[0] = 0;
64         F(sum);
65         printf("%d\n", dp[sum]);
66         cas++;
67     }
68     return 0;
69 }

HDOJ 1560 DNA sequence 状压dp 或 IDA*

时间: 2024-12-16 14:38:39

HDOJ 1560 DNA sequence 状压dp 或 IDA*的相关文章

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 &

HDOJ 4906 Our happy ending 状压DP(数位DP?)

http://acm.hdu.edu.cn/showproblem.php?pid=4906 题意: N个数的序列,每个数可以选择填0-L,如果一个序列可以选出某些数,他们的和为K,那么这个序列就是”好序列“,给定N<=20,K<=20,0<=L<=10^9,问好序列的个数. 分析: N和K很小,所以要想办法利用这个特性(状压?搜索?).虽然L很大,但实际上一个数大于K的时候,肯定是不能选他组成K的.我们就先考虑L<=K的做法. 然后还是考虑不出来.. 好吧,看题解吧.. 目

HDOJ 5135 Little Zu Chongzhi&#39;s Triangles 状压DP

状压DP Little Zu Chongzhi's Triangles Time Limit: 2000/1000 MS (Java/Others)    Memory Limit: 512000/512000 K (Java/Others) Total Submission(s): 88    Accepted Submission(s): 49 Problem Description Zu Chongzhi (429–500) was a prominent Chinese mathemat

[SCU 4501] DNA序列 (状压DP)

SCU - 4501 给定若干个DNA序列,求最短包含所有序列的长度 包含不一定是连续包含,可以不是子串 状压DP 依次构造每一位 把每个字符串走到的位置标记一下,压成6进制数 然后每个状态拓展一个字符串 然后同时拓展其他所有下一位与其相同的串 然后把状态丢到队列里转移,当每个串都走到结尾时输出答案 可以保证答案最多不超过40 时间复杂度 O(ans?lenN) #pragma comment(linker, "/STACK:102400000,102400000") #include

HDOJ 5418 Victor and World 状压DP

水状压DP Victor and World Time Limit: 4000/2000 MS (Java/Others)    Memory Limit: 262144/131072 K (Java/Others) Total Submission(s): 407    Accepted Submission(s): 164 Problem Description After trying hard for many years, Victor has finally received a p

HDOJ 5067 Harry And Dig Machine 状压DP

状压DP....dp[i][j]已经走过的点的状态,目前再j点的最小距离 Harry And Dig Machine Time Limit: 2000/1000 MS (Java/Others)    Memory Limit: 32768/32768 K (Java/Others) Total Submission(s): 560    Accepted Submission(s): 210 Problem Description As we all know, Harry Porter le

POJ 1795 DNA Laboratory (贪心+状压DP)

题意:给定 n 个 字符串,让你构造出一个最短,字典序最小的字符串,包括这 n 个字符串. 析:首先使用状压DP,是很容易看出来的,dp[s][i] 表示已经满足 s 集合的字符串以 第 i 个字符串结尾,他很容易就求得最短长度,但是这个字符串怎么构造呢, 由于要字典序最小,所以就不好搞了,挺麻烦的,所以我们利用贪心的思路,我们可以这样定义,dp[s][i] 表示已经满足 s 集合的字符串以 第 i 个字符串开头, 从后向前放,状态转移方程为:dp[s|(1<<i)][i] = min{ dp

[hdu 4899]14年多校第四场C Hero meet devil 状压DP

Time Limit: 16000/8000 MS (Java/Others)    Memory Limit: 131072/131072 K (Java/Others) Total Submission(s): 122    Accepted Submission(s): 49 Problem Description There is an old country and the king fell in love with a devil. The devil always asks th

UVA 1252 Twenty Questions 状压DP

简单状压DP: 当前状态s如果这个物品有状态a个属性,枚举下一个要猜测的特征k dp[s][a]=min(dp[s][a],max(dp[s+k][a],dp[s+k][a+k])+1); 4643 - Twenty Questions Asia - Tokyo - 2009/2010 Consider a closed world and a set of features that are defined for all the objects in the world. Each feat