首页 > 代码库 > HDOJ 1560 DNA sequence 状压dp 或 IDA*
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+。
额。。找到了当时写在文档里的一点点题解,比现在回顾写得清晰一点吧。。
<style></style><style></style>正解是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 else41 {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 }
声明:以上内容来自用户投稿及互联网公开渠道收集整理发布,本网站不拥有所有权,未作人工编辑处理,也不承担相关法律责任,若内容有误或涉及侵权可进行投诉: 投诉/举报 工作人员会在5个工作日内联系你,一经查实,本站将立刻删除涉嫌侵权内容。