链接:点击打开链接
题意:给出n段基因的价值和组成,求一个长度为l的价值大于等于零最大的基因价值
代码:
#include <set>
#include <queue>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <iostream>
#include <algorithm>
using namespace std;
int n,m,rt;
int v[15],f[(1<<10)+5];
int dp[2][1005][(1<<10)+5];
struct node{
int c[4],dis,fail;
}s[1005];
int get(char c){
if(c=='A') return 0;
if(c=='G') return 1;
if(c=='C') return 2;
if(c=='T') return 3;
}
void in(char ss[],int id){
int i,u;
u=0;
for(i=0;ss[i];i++){
if(s[u].c[get(ss[i])]==0)
s[u].c[get(ss[i])]=rt++;
u=s[u].c[get(ss[i])];
}
s[u].dis=(1<<id);
}
void getfail(){
int i,u,v,tmp;
queue<int> qu;
qu.push(0);
while(qu.size()){
u=qu.front();
qu.pop();
for(i=0;i<4;i++){
if(v=s[u].c[i]){
if(u==0)
s[v].fail=0;
else{
tmp=s[u].fail;
while(tmp&&s[tmp].c[i]==0)
tmp=s[tmp].fail;
s[v].fail=s[tmp].c[i];
s[v].dis|=s[s[tmp].c[i]].dis;
}
qu.push(v);
}
else
s[u].c[i]=s[s[u].fail].c[i];
}
}
}
int ac(){ //dp[i][j][k]长度是i,在第j个节点,状态是k
int i,j,k,op,ans,sta,tmp; //的可能,需要滚动数组
memset(dp,0,sizeof(dp));
op=0;
dp[0][0][0]=1;
getfail();
for(i=0;i<m;i++){
memset(dp[op^1],0,sizeof(dp[op^1]));
for(j=0;j<rt;j++){
for(sta=0;sta<(1<<n);sta++){
if(dp[op][j][sta]>0){
for(k=0;k<4;k++){
dp[op^1][s[j].c[k]][sta|s[s[j].c[k]].dis]=1;
}
}
}
}
op^=1;
}
ans=-1;
for(i=0;i<rt;i++){
for(j=0;j<(1<<n);j++){
if(dp[op][i][j]>0&&f[j]>=0){ //要注意是大于等于0的最大值
ans=max(ans,f[j]);
}
}
}
return ans;
}
int main(){ //提前处理出所有状态的价值,再在
int i,j,ans; //自动机上dp就行,就变成了hdu2825
char ss[105];
while(scanf("%d%d",&n,&m)!=EOF){
rt=1;
memset(s,0,sizeof(s));
for(i=0;i<n;i++){
scanf("%s%d",ss,&v[i]);
in(ss,i);
}
memset(f,0,sizeof(f));
for(i=0;i<(1<<n);i++){
for(j=0;j<n;j++){
if(i&(1<<j))
f[i]+=v[j];
}
}
ans=ac();
if(ans==-1)
puts("No Rabbit after 2012!");
else
printf("%d\n",ans);
}
return 0;
}