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. 在MyEclipse显示struts2源码和doc文档及自动完成功能

    分类: struts2 2010-01-07 16:34 1498人阅读 评论(1) 收藏 举报 myeclipsestruts文档xmlfileurl 在MyEclipse显示struts2源码和d ...

  2. RGB与16进制颜色转换的原理

    Integer有进制转换的方法.也可以自己写进制转换的方法.

  3. C++11:新式的字符串字面常量(String Literal)

    自C++11起,我们可以定义 raw string 字符串字面常量. Raw string 允许我们定义所见即所得的字符串字面常量,从而可以省下很多用来修饰特殊 字符的符号. Raw string 以 ...

  4. github代码收集推荐

    https://github.com/AFNetworking/AFNetworkinghttps://github.com/jessesquires/JSQMessagesViewControlle ...

  5. js限制文本框只能输入数字方法小结(转)

    这篇文章主要分享下js代码限制文本框中只能输入数字的多个实例,学习下js控制文本框中输入数字的方法,需要的朋友可以参考下   有时需要限制文本框输入内容的类型,本节分享下正则表达式限制文本框只能输入数 ...

  6. Java中静态内部类的理解

    class A { public void func() { A a=new A(); C c=a.new C(); } public static void main(String[] args) ...

  7. 字符串判断设置TextView高度

    问题:项目中需要根据字符串的长度判断Textview的高度   一.如果全是英文的也比较容易,根据长度判断从而设置mTextView的高度就好. double temp = str.length(); ...

  8. String类常用方法小节

    (1)String.equals() 返回值是boolean类型 equals(Object anObject)           将此字符串与指定的对象比较. (2)length() 返回值是in ...

  9. [SHELL]判断一个命令是否存在

    首先要说明的是,不要使用which来进行判断,理由如下: 1.which非SHELL的内置命令,用起来比内置命令的开销大,并且非内置命令会依赖平台的实现,不同平台的实现可能不同. # type typ ...

  10. 2016 - 1 - 25 第三方网络框架 AFN的简单使用

    AFNetworking 底层是对NSURlSession 和对 NSURLConnect 的包装 1.具体使用方法可以参照github上的主页面,在这里只是举一个文件上传的简单列子 - (void) ...