Rescue the Rabbit

Time Limit: 20000/10000 MS (Java/Others)    Memory Limit: 32768/32768 K (Java/Others)
Total Submission(s): 2036    Accepted Submission(s): 591

Problem Description
Dr. X is a biologist, who likes rabbits very much and can do everything for them. 2012 is coming, and Dr. X wants to take some rabbits to Noah's Ark, or there are no rabbits any more.

A rabbit's genes can be expressed as a string whose length is l (1 ≤ l ≤ 100) containing only 'A', 'G', 'T', 'C'. There is no doubt that Dr. X had a in-depth research on the rabbits' genes. He found that if a rabbit gene contained a particular gene segment, we could consider it as a good rabbit, or sometimes a bad rabbit. And we use a value W to measure this index.

We can make a example, if a rabbit has gene segment "ATG", its W would plus 4; and if has gene segment "TGC", its W plus -3. So if a rabbit's gene string is "ATGC", its W is 1 due to ATGC contains both "ATG"(+4) and "TGC"(-3). And if another rabbit's gene string is "ATGATG", its W is 4 due to one gene segment can be calculate only once.

Because there are enough rabbits on Earth before 2012, so we can assume we can get any genes with different structure. Now Dr. X want to find a rabbit whose gene has highest W value. There are so many different genes with length l, and Dr. X is not good at programming, can you help him to figure out the W value of the best rabbit.

 
Input
There are multiple test cases. For each case the first line is two integers n (1 ≤ n ≤ 10),l (1 ≤ l ≤ 100), indicating the number of the particular gene segment and the length of rabbits' genes.

The next n lines each line contains a string DNAi and an integer wi (|wi| ≤ 100), indicating this gene segment and the value it can contribute to a rabbit's W.

 
Output
For each test case, output an integer indicating the W value of the best rabbit. If we found this value is negative, you should output "No Rabbit after 2012!".
 
Sample Input
2 4
ATG 4
TGC -3
 
1 6
TGC 4
 
4 1
A -1
T -2
G -3
C -4
 
Sample Output
4
4
No Rabbit after 2012!
 
题目大意:给n个字符串,每个都有权值,其他的字符串没有权值。构造一个长度为m的权值最大的字符串,输出最大权值。每个带权字符串只能计算一次。
题目分析:容易想到在AC自动机上动态规划。内存要求比较高,用下滚动数组。
 
代码一:
# include<iostream>
# include<cstdio>
# include<queue>
# include<cstring>
# include<algorithm>
using namespace std; const short N=1005;
const short INF=0x7fff; short ch[N][4];
short sz;
short val[N]; void init()
{
sz=0;
memset(ch,-1,sizeof(ch));
memset(val,0,sizeof(val));
} short idx(char c)
{
if(c=='A') return 0;
else if(c=='T') return 1;
else if(c=='C') return 2;
else if(c=='G') return 3;
} void insert(char *s,short x)
{
short r=0;
short n=strlen(s);
for(short i=0;i<n;++i){
short c=idx(s[i]);
if(ch[r][c]==-1) ch[r][c]=++sz;
r=ch[r][c];
}
val[r]=x;
} void getFail()
{
short *fail=new short[sz+1];
queue<short>q;
fail[0]=0;
for(short i=0;i<4;++i){
if(ch[0][i]==-1)
ch[0][i]=0;
else{
fail[ch[0][i]]=0;
q.push(ch[0][i]);
}
}
while(!q.empty())
{
short u=q.front();
q.pop();
val[u]|=val[fail[u]];
for(short i=0;i<4;++i){
if(ch[u][i]==-1)
ch[u][i]=ch[fail[u]][i];
else{
fail[ch[u][i]]=ch[fail[u]][i];
q.push(ch[u][i]);
}
}
}
delete []fail;
} char s[6]; void solve(short n,short m,short *w)
{
short*** dp=new short**[2];
for(short i=0;i<2;++i){
dp[i]=new short*[sz+1];
for(short j=0;j<=sz;++j){
dp[i][j]=new short[1<<n];
}
} for(short i=0;i<=sz;++i) for(short j=0;j<(1<<n);++j)
dp[0][i][j]=-INF;
dp[0][0][0]=0;
short flag=1;
for(short i=0;i<m;++i,flag^=1){
for(short j=0;j<=sz;++j)
for(short k=0;k<(1<<n);++k)
dp[flag][j][k]=-INF;
for(short j=0;j<=sz;++j){
for(short k=0;k<(1<<n);++k){
if(dp[flag^1][j][k]==-INF)
continue;
for(short c=0;c<4;++c){
short v=ch[j][c];
short tempw=0;
for(short l=0;l<n;++l){
if(!(k&(1<<l))&&(val[v]&(1<<l)))
tempw+=w[l];
}
short &nxt=dp[flag][v][k|val[v]];
if(nxt<dp[flag^1][j][k]+tempw)
nxt=dp[flag^1][j][k]+tempw;
}
}
}
}
short ans=-INF;
for(short i=0;i<=sz;++i)
for(short j=0;j<(1<<n);++j)
ans=max(ans,dp[flag^1][i][j]);
if(ans>=0)
cout<<ans<<endl;
else
printf("No Rabbit after 2012!\n"); for(short i=0;i<2;++i){
for(short j=0;j<=sz;++j){
delete []dp[i][j];
}
delete []dp[i];
}
delete dp;
} int main()
{
short n,m;
while(cin>>n>>m)
{
init();
short *w=new short[n];
for(short i=0;i<n;++i){
scanf("%s%d",s,w+i);
insert(s,1<<i);
}
getFail();
solve(n,m,w);
delete []w;
}
return 0;
}

  

代码二:

# include<iostream>
# include<cstdio>
# include<queue>
# include<cstring>
# include<algorithm>
using namespace std; const int N=1005;
const int INF=0x7fff; int ch[N][4];
int sz;
int val[N]; void init()
{
sz=0;
memset(ch,-1,sizeof(ch));
memset(val,0,sizeof(val));
} int idx(char c)
{
if(c=='A') return 0;
else if(c=='T') return 1;
else if(c=='C') return 2;
else if(c=='G') return 3;
} void insert(char *s,int x)
{
int r=0;
int n=strlen(s);
for(int i=0;i<n;++i){
int c=idx(s[i]);
if(ch[r][c]==-1) ch[r][c]=++sz;
r=ch[r][c];
}
val[r]=x;
} void getFail()
{
int *fail=new int[sz+1];
queue<int>q;
fail[0]=0;
for(int i=0;i<4;++i){
if(ch[0][i]==-1)
ch[0][i]=0;
else{
fail[ch[0][i]]=0;
q.push(ch[0][i]);
}
}
while(!q.empty())
{
int u=q.front();
q.pop();
val[u]|=val[fail[u]];
for(int i=0;i<4;++i){
if(ch[u][i]==-1)
ch[u][i]=ch[fail[u]][i];
else{
fail[ch[u][i]]=ch[fail[u]][i];
q.push(ch[u][i]);
}
}
}
delete []fail;
} char s[6];
int w[10];
int dp[2][N+1][1<<10]; int get(int s,int n)
{
int res=0;
for(int i=0;i<n;++i)
if(s&(1<<i)) res+=w[i];
return res;
} void solve(int n,int m)
{
memset(dp,0,sizeof(dp));
dp[0][0][0]=1;
int flag=1;
for(int i=0;i<m;++i,flag^=1){
memset(dp[flag],0,sizeof(dp[flag]));
for(int j=0;j<=sz;++j){
for(int k=0;k<(1<<n);++k) if(dp[flag^1][j][k]){
for(int c=0;c<4;++c)
dp[flag][ch[j][c]][k|val[ch[j][c]]]=1;
}
}
}
int ans=-INF;
for(int s=0;s<(1<<n);++s){
int temp=get(s,n);
for(int i=0;i<=sz;++i){
if(dp[flag^1][i][s]&&temp>ans){
ans=temp;
break;
}
}
}
if(ans>=0)
cout<<ans<<endl;
else
printf("No Rabbit after 2012!\n");
} int main()
{
int n,m;
while(cin>>n>>m)
{
init();
for(int i=0;i<n;++i){
scanf("%s%d",s,w+i);
insert(s,1<<i);
}
getFail();
solve(n,m);
}
return 0;
}

  

HDU-4057 Rescue the Rabbit(AC自动机+DP)的更多相关文章

  1. HDU 4057 Rescue the Rabbit(AC自动机+DP)

    题目链接 一个数组开小了一点点,一直提示wa,郁闷,这题比上个题简单一点. #include <iostream> #include <cstring> #include &l ...

  2. HDU 4057 Rescue the Rabbit ( AC自动机 + 状态压缩DP )

    模板来自notonlysuccess. 模式串只有10个,并且重复出现的分值不累加,因此很容易想到状态压缩. 将模式串加入AC自动机,最多有10*100个状态. dp[i][j][k]:串长为i,在T ...

  3. HDU 3341 Lost's revenge AC自动机+dp

    Lost's revenge Time Limit: 15000/5000 MS (Java/Others)    Memory Limit: 65535/65535 K (Java/Others)T ...

  4. HDU 2457 DNA repair(AC自动机+DP)题解

    题意:给你几个模式串,问你主串最少改几个字符能够使主串不包含模式串 思路:从昨天中午开始研究,研究到现在终于看懂了.既然是多模匹配,我们是要用到AC自动机的.我们把主串放到AC自动机上跑,并保证不出现 ...

  5. HDU 2425 DNA repair (AC自动机+DP)

    DNA repair Time Limit: 5000/2000 MS (Java/Others)    Memory Limit: 32768/32768 K (Java/Others)Total ...

  6. hdu 4057 Rescue the Rabbit

    题意 给出n(n<=10)个串,每个串有个权值,然后让你构造一个长度为l(l<=100)的串,如果他包含给出的串就得到相应的权值,求可能得到的最大权值 解法 AC自动机+DP,很显然要建立 ...

  7. HDU 4758 Walk Through Squares(AC自动机+DP)

    题目链接 难得出一个AC自动机,我还没做到这个题呢...这题思路不难想,小小的状压出一维来,不过,D和R,让我wa死了,AC自动机,还得刷啊... #include<iostream> # ...

  8. HDU 2825 Wireless Password【AC自动机+DP】

    给m个单词,由这m个单词组成的一个新单词(两个单词可以重叠包含)长度为n,且新单词中包含的基本单词数目不少于k个.问这样的新单词共有多少个? m很小,用二进制表示新单词中包含基本单词的情况. 用m个单 ...

  9. hdu4057Rescue the Rabbit(ac自动机+dp)

    链接 当时是因为没有做出来这道题才开了自动机的专题,现在看看还是比较简单的. 因为每个病毒串只算一次,只有10个病毒串,可以状压一下哪些状态是可以达到的,最后取一个最大值. #include < ...

  10. HDU 6086 Rikka with String AC自动机 + DP

    Rikka with String Problem Description As we know, Rikka is poor at math. Yuta is worrying about this ...

随机推荐

  1. 去除 UINavigationController.navigationBar下方的横线

    self.navigationController.navigationBar.clipsToBounds=YES;

  2. 错误:媒体集有 2 个媒体簇,但只提供了 1 个 sql2005 备份错误。

    错误:媒体集有 2 个媒体簇,但只提供了 1 个 sql2005 2010-10-19 11:44:06|  分类: sql|举报|字号 订阅     ql2005备份的时候,选择备份路径是一方面,但 ...

  3. sqlite的常用语法

    sqllite 增删改查创建表的语法 创建表db.execSQL("create table user(_id integer primary key autoincrement,numbe ...

  4. 2014年5月份第4周51Aspx源码发布详情

    最基本wcf服务器与客户端交互源码  2014-5-26 [VS2003]源码描述:本示例讲解的是最基本的wcf语法,示例浏览请先运行服务端,然后在运行客户端,适合想要学习wcf的初学者.仅供借鉴,欢 ...

  5. coding题都在考察我们的什么技能

    其实不是都在考我们的算法设计,有的时候算法简单,但是coding却可能不那么简单,比如下面这道题目: 题:写一个把字符串的IP地址变成32位整数的函数,要求考察程序健壮性. 这题初看起来一点都不难,但 ...

  6. poj2763

    //Accepted 11676 KB 2344 ms /* source:poj2763 time :2015.5.29 by :songt */ /*题解: 树链剖分 基于边权,路径查询 wind ...

  7. C语言程序设计第12次作业

    一.本次课主要内容: 本章主要介绍指针相关的基础知识,本节课的主要如下 (1)通过示例"电码加密"引入字符指针与字符串处理.首先重点介绍字符指针和字符串的关联和区别,然后对常用字符 ...

  8. 0427 scrum & 读后感

    5.Scrum团队成立 5.1 团队名称,团队目标.团队口号.团队照: 5.2 角色分配 6. 团队项目选题 详情见团队博客:http://www.cnblogs.com/alfredzhu/ htt ...

  9. How to upgrade Subversion on OSX

    How to upgrade Subversion on OSX http://andowebsit.es/blog/noteslog.com/post/how-to-upgrade-subversi ...

  10. java集合类的学习(二)

    ArrayList,LinkedList,Vector都是List的实现类,前两都没有实现同步机制,Vector实现了同步机制.他们代码类似. ArrayList代表大小可变的数组,允许对元素进行快速 ...