万恶之源

翻译

题意就是给出N个DNA序列,要求出一个包含这n个序列的最短序列是多长

这是一道搜索题,为什么呢?从样例可以感受到,我们应该从左往右“扫描”,从n个DNA序列中取出某个特定的字母,直到n个序列都被取空。题目便是要求这个“取出”次数的最小值。而我们每次都选择A,T,C,G中的其中一个取出,这样便形成了一个不断以4个叶子延申的搜索树了。(请自行脑补)(当然实际必须要剪掉)

IDA*

这题很适合用IDA*,随着深度不断增加,第一个访问到的答案一定是最优解。而庞大的数据,也需要我们设计一个评估函数。

剪枝

我们使用评估函数来进行剪枝。很自然可以想到,我们用已经处理完的长度,加上估计还需要的长度,它如果大于给定的长度,那么这种方法就是不可行的,那么我们就可以退出。

具体而言,有两种方法可以进行待处理长度的预测。一种是计算当前各序列未就位的序列的最大长度;另外一种是统计各个字母在所有序列的未就位的序列中的最大数量之和

实践表明,后者是更优的。

布尔型的函数

对于返回值的理解,首先这个dfs函数是布尔型的,剪枝即判错,其它情况下,返回值则是下一层的子函数的返回值,下一层的返回值又是由下下一层的返回值决定的……不断这样递归下去,当找到正确答案时那就会不断返回true直至给第一个母函数啦。具体而言,首先在dfs的开头要剪枝,然后用一个循环对不同操作再次进行搜索,这若干个操作之中若有一个为真,那么这个函数就会返回真;只有当他们全部返回假,当前这个函数才会返回假。

过程中的重大错误

  • 把int类型的eva函数写成了bool,导致所有非0的数都变成了 1
  • 忘记给递归函数的某些路径设置返回值,导致函数返回异常值,明明是bool类型的函数,居然返回了4。。。影响了后续的判断(我当时还忽略了编译器的友情提醒:不是所有的路径都返回值...)
  • 当有多次操作时,要注意状态的初始化,包括各种数组与一些最大最小值等任何一个过程中需要的变量都要检查。

代码

#include<iostream>
#include<string>
#include<cstring>
#include<algorithm>
using namespace std;
int T, n;//T是总问题数,n是每个问题里面有多少个DNA序列 struct node {
int len;
string str;
}dna[10];
char part[5] = { 'A', 'T', 'G', 'C' };//扫描的顺序,不一定是这个,只是说按我这个顺序来进行操作然后接着dfs
int pos[10] = { 0 };//记录第i个字符串扫描到了第几位
int eva() {
int maxn = -1;
for (int i = 0; i < n; i++) {
maxn = max(maxn, dna[i].len - pos[i]);
}
return maxn;
}
int eva2() {//比第eva快了二十倍
int ans = 0;
int cnt[4] = { 0 };
int maxn[4] = { 0 };
for (int i = 0; i < n; i++) {
int a = 0, b = 0, c = 0, d = 0;
for (unsigned int j = pos[i]; j < dna[i].str.length(); j++) {
if (dna[i].str[j] == 'A') cnt[0]++;
if (dna[i].str[j] == 'T') cnt[1]++;
if (dna[i].str[j] == 'G') cnt[2]++;
if (dna[i].str[j] == 'C') cnt[3]++;
}
for (int k = 0; k < 4; k++) {
maxn[k] = max(maxn[k], cnt[k]);
cnt[k] = 0;
}
}
for (auto i : maxn)
ans += i;
return ans;
}
bool IDA(int now, int dep) {
int e = eva2();
//printf("e is %d, now is %d, dep is %d\n", e, now, dep); if (now > dep) return false;//最后一个dfs返回false的条件
if (now + e > dep) return false;//剪枝
if (e == 0) return true;////最后一个dfs返回true的条件 //这函数应该是bool类型的吗?这样只有某一个子函数会为真吧?那最开始的那个呢?---不断递归,不断返回
//整个函数返回true的条件是什么,应该不是放在开头吧---开头的可以保证最后一个dfs返回真,结尾的可以保证过程中的dfs返回真(false同理) int tep[10] = { 0 };
memcpy(tep, pos, sizeof(tep));
for (int i = 0; i < 4; i++) {
int flag = 0;
for (int j = 0; j < n; j++) {
// printf("i is %d, j is %d\n", i, j);
if (dna[j].str[pos[j]] == part[i]) {
pos[j]++;
flag = 1;
}
}
/*
for (int j = 0; j < n && flag; j++)
printf("pos[%d] is %d\n", j, pos[j]);
cout << endl;
*/
if (flag) {
if (IDA(now + 1, dep))
return true;
}
memcpy(pos, tep, sizeof(pos));
}
return false;//没有这一句递归就无法进行,为什么?!
} int main(void) {
cin >> T;
while (T--) {
cin >> n;
memset(pos, 0, sizeof(pos)); int maxn = 1;
for (int i = 0; i < n; i++) {
cin >> dna[i].str;
dna[i].len = dna[i].str.length();
maxn = max(dna[i].len, maxn);
}
int dep;
for (dep = maxn;; dep++) {
memset(pos, 0, sizeof(pos));
if (IDA(0, dep)) break;
}
cout << dep << endl;
for (int i = 0; i < n; i++) {
dna[i].str.clear();
dna[i].len = 0;
}
} return 0;
}

IDA*、剪枝、较难搜索、扫描——DNA sequence HDU - 1560的更多相关文章

  1. DNA sequence HDU - 1560

    DNA sequence Time Limit: 15000/5000 MS (Java/Others)    Memory Limit: 32768/32768 K (Java/Others)Tot ...

  2. DNA sequence HDU - 1560(IDA*,迭代加深搜索)

    题目大意:有n个DNA序列,构造一个新的序列,使得这n个DNA序列都是它的子序列,然后输出最小长度. 题解:第一次接触IDA*算法,感觉~~好暴力!!思路:维护一个数组pos[i],表示第i个串该匹配 ...

  3. G - DNA sequence HDU - 1560

    题目链接: https://vjudge.net/contest/254151#problem/G AC代码: #include<iostream> #include<cstring ...

  4. hdu 1560 DNA sequence(迭代加深搜索)

    DNA sequence Time Limit : 15000/5000ms (Java/Other)   Memory Limit : 32768/32768K (Java/Other) Total ...

  5. HDU1560 DNA sequence —— IDA*算法

    题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=1560 DNA sequence Time Limit: 15000/5000 MS (Java/Oth ...

  6. Hdu1560 DNA sequence(IDA*) 2017-01-20 18:53 50人阅读 评论(0) 收藏

    DNA sequence Time Limit : 15000/5000ms (Java/Other)   Memory Limit : 32768/32768K (Java/Other) Total ...

  7. HDU1560 DNA sequence(IDA*)题解

    DNA sequence Time Limit: 15000/5000 MS (Java/Others)    Memory Limit: 32768/32768 K (Java/Others) To ...

  8. hdu 1560 DNA sequence(搜索)

    http://acm.hdu.edu.cn/showproblem.php?pid=1560 DNA sequence Time Limit: 15000/5000 MS (Java/Others)  ...

  9. HDU 1560 DNA sequence(DNA序列)

    HDU 1560 DNA sequence(DNA序列) Time Limit: 15000/5000 MS (Java/Others)    Memory Limit: 32768/32768 K  ...

随机推荐

  1. CDI Features inJavaEE 的上下文和依赖注入

    基本的CDI的功能: 类型安全:CDI使用Java类型来解析注入,而不是通过(字符串)名称注入对象.当类型不足时, 可以使用限定符 注释.这允许编译器轻松检测错误,并提供简单的重构. POJO:几乎每 ...

  2. trait能力在PHP中的使用

    相信大家对trait已经不陌生了,早在5.4时,trait就已经出现在了PHP的新特性中.当然,本身trait也是特性的意思,但这个特性的主要能力就是为了代码的复用. 我们都知道,PHP是现代化的面向 ...

  3. Java基础系列(20)- while循环

    循环结构 while循环 do-循环 for循环 在java5中引入了一种主要用于数组的增强型for循环 while循环 while是最基本的循环,它的结构为 while(布尔表达式){ //循环内容 ...

  4. JDK1.8源码(三)——java.lang.String类

    一.概述 1.介绍 String是一个final类,不可被继承,代表不可变的字符序列,是一个类类型的变量.Java程序中的所有字符串字面量(如"abc")都作为此类的实例实现,&q ...

  5. Matlab使用随记

    Matlab 2020 想要看图像每一点的值大小 工具--->数据提示 想要导出的分辨率提高 导出设置--->渲染--->600dpi Matlab 2017b 程序运行后,画出图, ...

  6. 华为云计算IE面试笔记-云磁盘和普通磁盘的区别。

    1. 定义 云硬盘:一种虚拟块存储服务,主要为ECS和BMS提供块存储空间 普通磁盘:也称本地硬盘,指挂载在计算实例物理机上的本地硬盘 2. 性能 吞吐量具体情况具体分析.(若云磁盘用的SSD本地磁盘 ...

  7. 鸿蒙内核源码分析(定时器篇) | 哪个任务的优先级最高 | 百篇博客分析OpenHarmony源码 | v31.02

    百篇博客系列篇.本篇为: v31.xx 鸿蒙内核源码分析(定时器篇) | 哪个任务的优先级最高 | 51.c.h .o 本篇说清楚定时器的实现 读本篇之前建议先读鸿蒙内核源码分析(总目录)其余篇. 运 ...

  8. 鸿蒙内核源码分析(汇编基础篇) | CPU在哪里打卡上班? | 百篇博客分析OpenHarmony源码 | v22.01

    百篇博客系列篇.本篇为: v22.xx 鸿蒙内核源码分析(汇编基础篇) | CPU在哪里打卡上班 | 51.c.h .o 硬件架构相关篇为: v22.xx 鸿蒙内核源码分析(汇编基础篇) | CPU在 ...

  9. IdentityServer4[4]使用密码保护API资源

    使用密码保护API资源(资源所有者密码授权模式) 资源所有者(Resource Owner)就是指的User,也就是用户.所以也称为用户名密码模式.相对于客户端凭证模式,增加了一个参与者User.通过 ...

  10. Chrome浏览器启动参数大全(命令行参数)

    前言 在开发Web项目当中,浏览器必不可少,而浏览器的启动参数可以帮我们实现很多功能. 常用参数 常用参数请参考下表. 序号 参数 说明 1 --allow-outdated-plugins 不停用过 ...