程序设计实习2015年期末考试 E.DNA(状态压缩dp+特殊处理+预处理)
2016-06-12 19:07
344 查看
程序设计实习2015年期末考试 E.DNA(状态压缩+特殊处理+预处理)
总时间限制: 6000ms 内存限制: 1024kB
描述
考虑一段DNA单链,上面有N个基因片段。这里的基因片段可重叠(例如AGCTC包含AGC和CTC),不可倒置(例如AGCTC不包含TCG)。要问这样的单链最短长度是多少。
输入
输入的第一行是一个正整数T(不超过13),表示数据组数。每组数据若干行,其中第一行一个正整数N(不超过9),表示基因片段的数目,接下来N行每行一个基因片段,由AGCT四个字母组成,且长度介于1和15之间(含两端)。
输出
每组数据输出一样,表示最短的单链长度包含这N个基因片段。
样例输入
1
5
TCGG
GCAG
CCGC
GATC
ATCG
样例输出
11
这个题一看到就想到状态压缩dp,但是光组成状态这一个维度是不够的,因为同一个状态由于排列不同添加一个DNA片段代价不一样,所以我第一反应添加了另外一个维度——结尾的字符串。但是WA,当时想到一个问题,万一最后一个DNA片段长得一个片段解决不了要多个呢,那么这个状态压缩岂不是得改成dfs了,心凉了半截,改为dfs,TLE。陷入了死胡同。
其实,我之所以状态压缩也许只是我觉得似乎是状态压缩,并没有自己的思考,我连上一个问题都没想明白就开始写,就算对了也是瞎蒙的。痛定思痛想了想,想明白了这个问题:
如果在ABC这个串后面加了一个D,D在BC内是一个子片段,虽然算不出正确结果,但是由于必然计算过AB+D+C=ABC这一形式的状态压缩dp局部解,所以ABC+D这个错误解答不会影响。但是,如果D是C的一个子片段,那么问题就很产生了,为了避免这个错误,要特殊处理,读入一个片段后判断是否被前面的串包含,包含则删去,这样算法才具有了正确性。
特殊处理后本题算法就有了正确性保证,预处理dis[i][j]表示i后接上j可以重叠长度。一个小技巧,合理调用< string.h>内的库函数strstr()可以节省查找子串代码量,性能也不差。
总时间限制: 6000ms 内存限制: 1024kB
描述
考虑一段DNA单链,上面有N个基因片段。这里的基因片段可重叠(例如AGCTC包含AGC和CTC),不可倒置(例如AGCTC不包含TCG)。要问这样的单链最短长度是多少。
输入
输入的第一行是一个正整数T(不超过13),表示数据组数。每组数据若干行,其中第一行一个正整数N(不超过9),表示基因片段的数目,接下来N行每行一个基因片段,由AGCT四个字母组成,且长度介于1和15之间(含两端)。
输出
每组数据输出一样,表示最短的单链长度包含这N个基因片段。
样例输入
1
5
TCGG
GCAG
CCGC
GATC
ATCG
样例输出
11
这个题一看到就想到状态压缩dp,但是光组成状态这一个维度是不够的,因为同一个状态由于排列不同添加一个DNA片段代价不一样,所以我第一反应添加了另外一个维度——结尾的字符串。但是WA,当时想到一个问题,万一最后一个DNA片段长得一个片段解决不了要多个呢,那么这个状态压缩岂不是得改成dfs了,心凉了半截,改为dfs,TLE。陷入了死胡同。
其实,我之所以状态压缩也许只是我觉得似乎是状态压缩,并没有自己的思考,我连上一个问题都没想明白就开始写,就算对了也是瞎蒙的。痛定思痛想了想,想明白了这个问题:
如果在ABC这个串后面加了一个D,D在BC内是一个子片段,虽然算不出正确结果,但是由于必然计算过AB+D+C=ABC这一形式的状态压缩dp局部解,所以ABC+D这个错误解答不会影响。但是,如果D是C的一个子片段,那么问题就很产生了,为了避免这个错误,要特殊处理,读入一个片段后判断是否被前面的串包含,包含则删去,这样算法才具有了正确性。
特殊处理后本题算法就有了正确性保证,预处理dis[i][j]表示i后接上j可以重叠长度。一个小技巧,合理调用< string.h>内的库函数strstr()可以节省查找子串代码量,性能也不差。
Accepted 260kB 0ms 1527 B G++
#define MAX_N 9 #define MAX_LEN 15 #define INF MAX_N*MAX_LEN #include<stdio.h> #include<memory.h> #include<string.h> int cases,n,ans; char s[MAX_N][MAX_LEN+1]; int l[MAX_N]; int dp[1<<MAX_N][MAX_N];//状态/结尾 int common[MAX_N][MAX_N],c; bool ok; int f(int state,int i) { //printf("%d %d\n",state,i); if (dp[state][i]) return dp[state][i]; dp[state][i]=INF; for (int j=0;j<n;j++) if (i!=j && ((state&(1<<j))!=0)) if (f(state^(1<<j),j)+l[i]-common[j][i]<dp[state][i]) dp[state][i]=f(state^(1<<j),j)+l[i]-common[j][i]; return dp[state][i]; } int main() { //freopen("input.txt","r",stdin); scanf("%d\n",&cases); while (cases--) { memset(dp,0,sizeof(dp)); memset(s,0,sizeof(s)); scanf("%d\n",&n); for (int i=0;i<n;i++) { scanf("%s\n",&s[i][0]); for (int j=0;j<i;j++) if (strstr(s[j],s[i])!=NULL) { i--; n--; break; } } for (int i=0;i<n;i++) dp[0][i]=l[i]=strlen(s[i]); for (int i=0;i<n;i++) for (int j=0;j<n;j++) if (i!=j) { c=l[i]<l[j]?l[i]:l[j]; ok=false; while (c) { if (strstr(s[j],s[i]+l[i]-c)==s[j]) break; c--; } common[i][j]=c; //printf("%d %d:%d\n",i,j,common[i][j]); } ans=INF; for (int i=0;i<n;i++) if (f((1<<n)-(1<<i)-1,i)<ans) ans=f((1<<n)-(1<<i)-1,i); printf("%d\n",ans); } return 0; }
相关文章推荐
- Qt 4.7.2编译过程的简要记录
- 后台权限系统
- python enumerate用法总结
- 航电 2041 超级楼梯
- vs的lua项目,导出release版本在win上打印日志
- 孙鑫VC学习笔记:多线程编程
- "围观"设计模式(20)--行为型之策略模式(Strategy Pattern)
- JavaScript遍历求解数独问题的主要思路小结
- URI
- Linux中的c语言实现类似迅雷那样的下载
- iOS开发 报错process launch failed: timed out waiting for app to launch的解决方案
- ELK -分析nginx 日志
- 常用网络结构
- 飛飛(六十五)洗牌游戏解法二
- 栈的压入、弹出序列23
- ios开发使用Basic Auth 认证方式
- jzoj 2016.6.11noip模拟赛B总结
- App 即时通讯 SDK
- 第十五周学习进度条
- 飛飛(六十四)洗牌游戏解法一