IDA*、剪枝、较难搜索、扫描——DNA sequence HDU - 1560
翻译
题意就是给出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的更多相关文章
- DNA sequence HDU - 1560
DNA sequence Time Limit: 15000/5000 MS (Java/Others) Memory Limit: 32768/32768 K (Java/Others)Tot ...
- DNA sequence HDU - 1560(IDA*,迭代加深搜索)
题目大意:有n个DNA序列,构造一个新的序列,使得这n个DNA序列都是它的子序列,然后输出最小长度. 题解:第一次接触IDA*算法,感觉~~好暴力!!思路:维护一个数组pos[i],表示第i个串该匹配 ...
- G - DNA sequence HDU - 1560
题目链接: https://vjudge.net/contest/254151#problem/G AC代码: #include<iostream> #include<cstring ...
- hdu 1560 DNA sequence(迭代加深搜索)
DNA sequence Time Limit : 15000/5000ms (Java/Other) Memory Limit : 32768/32768K (Java/Other) Total ...
- HDU1560 DNA sequence —— IDA*算法
题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=1560 DNA sequence Time Limit: 15000/5000 MS (Java/Oth ...
- 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 ...
- HDU1560 DNA sequence(IDA*)题解
DNA sequence Time Limit: 15000/5000 MS (Java/Others) Memory Limit: 32768/32768 K (Java/Others) To ...
- hdu 1560 DNA sequence(搜索)
http://acm.hdu.edu.cn/showproblem.php?pid=1560 DNA sequence Time Limit: 15000/5000 MS (Java/Others) ...
- HDU 1560 DNA sequence(DNA序列)
HDU 1560 DNA sequence(DNA序列) Time Limit: 15000/5000 MS (Java/Others) Memory Limit: 32768/32768 K ...
随机推荐
- Apollo 配置中心详细教程
一.简介 Apollo(阿波罗)是携程框架部门研发的分布式配置中心,能够集中化管理应用不同环境.不同集群的配置,配置修改后能够实时推送到应用端,并且具备规范的权限.流程治理等特性,适用于微服务配置管理 ...
- idea创建Maven项目没有src目录,且依赖也没有更新
刚开始用idea的时候,重新配置安装了Maven,但是创建项目的时候发现创建的目录少了很多东西,今天重新查看了一下,发现了原因....... 话不多说,安装配置Maven的方法网上都有,我之前改路径的 ...
- vue-router路由钩子
路由跳转前后,需要做某些操作,这时就可以使用路由钩子来监听路由的变化. 接收三个参数: to: Route: 即将要进入的目标路由对象 from: Route: 当前导航正要离开的路由 next: F ...
- pip国内源设置
在目录 C:\Users\Administrator下新建pip目录 C:\Users\Administrator\pip 添加 pip.ini 文件 pip.ini内容设置为 [global] in ...
- list使用详解
List双向链表 再谈链表 List链表的概念再度出现了,作为线性表的一员,C++的STL提供了快速进行构建的方法,为此,在前文的基础上通过STL进行直接使用,这对于程序设计中快速构建原型是相当有必要 ...
- Django学习day13随堂笔记
每日测验 """ 今日考题 1.什么是django中间件,它的作用是什么,如何自定义中间件,里面有哪些用户可以自定义的方法,这些方法有何特点 2.基于django中间件的 ...
- 宝塔面板使用PM2命令提示Command Not Found解决方案
1.查看node版本 进入/www/server/nvm/versions/node 查看node版本 2.复制以下代码 以node版本v12.18.1举例 PATH=$PATH:/www/serve ...
- @RestController的用法
我一直都不太理解RESTFUL风格但是先记住一些基本用法在深入吧 ** * * 在服务端应用程序状态和功能可以分成各种资源,每一个资源都使用URL 得到一个唯一的地址,所有资源都共享统一的 * 接口, ...
- linux mint 18.1 安装备忘录
本次全新安装mint18.1,遇到一些问题,全部解决,怕日后忘记,再捣鼓琢磨,浪费时间,特记录在此: 一.楷体字体问题 安装完后的mint18.1,显示都是楷体,经请教薄荷论坛高手,可用以下办法解决: ...
- Fortran学习笔记:01 基本格式与变量声明
Fortran学习笔记目录 01 基本格式与变量声明 格式 固定格式(Fixed Format):Fortran77 程序需要满足一种特定的格式要求,具体形式参考教材 自由格式(Free Format ...