zoukankan      html  css  js  c++  java
  • HDU 4057 Rescue the Rabbit (AC自动机 + 状压DP)

    Rescue the Rabbit

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


    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!
    Hint
    case 1:we can find a rabbit whose gene string is ATGG(4), or ATGA(4) etc. case 2:we can find a rabbit whose gene string is TGCTGC(4), or TGCCCC(4) etc. case 3:any gene string whose length is 1 has a negative W.
     
    Author
    HONG, Qize
     
    Source
     
    Recommend
    lcy
     

     题目:给出一些模式串,每个串有一定的价值,现在构造一个长度为M的串,问最大的价值为多少,每个模式串最多统计一次。

    由于每个模式串最多统计一次,也算是降低了难度,最多10个串,容易想至于状态压缩。

    Trie树上的状态最多1000个,100*10,而最终的串长度最多为100

    容易想到的DP,dp[i][j][k],表示长度为i的串,位于Trie上的状态j,模式串的状态为k的最大价值。

    这个复杂度为100*1024*1000,题目给了10s,还是可以搞的,但是空间不够,只能用滚动数组了。

    先建立Trie树,以及失败指针,对于每一个结点,标号,静态的方便点。

    最终DP,通过模式串的状态确定当前价值

    #include<iostream>
    #include<cstdio>
    #include<cstring>
    
    using namespace std;
    
    const int N=100010;
    const int INF=0x3f3f3f3f;
    
    struct Trie{
        int count;
        int fail,next[4];
        void init(){
            memset(next,0,sizeof(next));
            fail=count=0;
        }
    }tree[N];
    
    int cnt,val[N],dp[2][1010][1<<10];
    char str[110];
    
    int find(char ch){
        switch(ch){
            case 'A':return 0;
            case 'T':return 1;
            case 'C':return 2;
            case 'G':return 3;
        }
        return 0;
    }
    
    void Insert(char *str,int k){
        int i=0,loc=0;
        while(str[i]!='\0'){
            int id=find(str[i]);
            if(tree[loc].next[id]==0){
                tree[++cnt].init();
                tree[loc].next[id]=cnt;
            }
            loc=tree[loc].next[id];
            i++;
        }
        tree[loc].count |= (1<<k);
    }
    
    void AC_automation(){
        int que[N];
        int head=0,tail=0;
        que[tail++]=0;
        while(head<tail){
            int cur=que[head++];
            for(int i=0;i<4;i++){
                if(tree[cur].next[i]==0)
                    tree[cur].next[i]=tree[tree[cur].fail].next[i];
                else{
                    int tmp=tree[cur].next[i];
                    if(cur)
                        tree[tmp].fail=tree[tree[cur].fail].next[i];
                    tree[tmp].count |= tree[tree[tmp].fail].count;
                    que[tail++]=tmp;
                }
            }
        }
    }
    
    int n,m;
    
    int get(int state){
        int ans=0;
        for(int i=0;i<n;i++)
            if(state&(1<<i))
                ans+=val[i];
        return ans;
    }
    
    void DP(){
        memset(dp,0,sizeof(dp));
        dp[0][0][0]=1;
        for(int i=1;i<=m;i++){
            memset(dp[i&1],0,sizeof(dp[i&1]));
            for(int j=0;j<=cnt;j++)
                for(int k=0;k<4;k++)
                    for(int r=0;r<(1<<n);r++)
                        if(dp[(i+1)&1][j][r])
                            dp[i&1][tree[j].next[k]][r|tree[tree[j].next[k]].count]=1;
        }
        int ans=-INF;
        for(int j=0;j<(1<<n);j++)
            for(int i=0;i<=cnt;i++)
                if(dp[m&1][i][j]){
                    ans=max(ans,get(j));
                    break;
                }
        if(ans<0)
            puts("No Rabbit after 2012!");
        else
            printf("%d\n",ans);
    }
    
    int main(){
    
        //freopen("input.txt","r",stdin);
    
        while(~scanf("%d%d",&n,&m)){
            tree[0].init();
            cnt=0;
            for(int i=0;i<n;i++){
                scanf("%s%d",str,&val[i]);
                Insert(str,i);
            }
            AC_automation();
            DP();
        }
        return 0;
    }
  • 相关阅读:
    Java动态规划实现将数组拆分成相等的两部分
    动态规划解决hdu龟兔赛跑
    Eclipse上将maven项目部署到tomcat,本地tomcat下,webapps下,web-inf下lib下没有jar包决绝方案
    【转】spring IOC和AOP的理解
    Eclipse创建一个普通的java web项目
    linux服务器自动备份与删除postgres数据库数据
    开启Linux服务器vnc远程桌面详细步骤
    设计模式---JDK动态代理和CGLIB代理
    菜谱
    网络协议-dubbo协议
  • 原文地址:https://www.cnblogs.com/jackge/p/3095799.html
Copyright © 2011-2022 走看看