group like pressure dp

  Some people claim to be, I deleted the tag

  This is a good question.

  A look at the $ c <= 16 $ decisively shaped pressure but how the pressure?

  One obvious idea is, upper and lower levels of enumeration state, the state of each layer has a limit of $ C (c, c / 2) $, c = 16, there are about 13,000 times, obviously dead.

  We consider another angle. A few too many upper and lower levels of the state, then we may wish to consider only one layer, and each point is only about four points up and down about it, when the dp only need to consider the number above and to the left, the extra point in the transfer after completion of the right and bottom lost usefulness, then we might as well throw them away.

  After this question I think this is relatively simple.

  We make $ f [i] [j] [k] $ represent the current consideration of i-th row j-th position, the state is the state k when the number of transfer ideas and plug dp somewhat similar, regardless of the current grid above and to the left if there are letters transfer to

  This question a lot of ideas are plug and dp some similar place.

  Theoretical complexity $ O (rc2 ^ c) $ , is far less than the actual (achieved complexity is right)

 1 #include<bits/stdc++.h>
 2 using namespace std;
 3 int r,c,cur,la,ans;
 4 char s[130][55];
 5 struct hash_map{
 6     int fi[23333],ne[6000005];
 7     int val[6000006],tot,f[6000005];
 8     inline void clear(){
 9         tot=0;memset(fi,0,sizeof(fi));
10     }
11     inline int &operator [](int x){
12         int y=x%23333,i=fi[y];
13         for(;i&&val[i]!=x;i=ne[i]);
14         if(!i) ne[++tot]=fi[y],fi[y]=i=tot,val[tot]=x,f[i]=0;
15         return f[i];
16     }
17 }g[2];
18 inline int count(int x,int y){
19     int cnt=0;
20     for(int i=0;i<y;i++) cnt+=((x&2)>>1),x>>=1;
21     return cnt;
22 }
23 inline int count2(int x,int y){
24     int cnt=0;
25     for(int i=c;i>=y;i--)
26         if(x&(1<<i)) cnt++;
27     return cnt;
28 }
29 int main(){
30     cin>>r>>c;
31     for(int i=1;i<=r;i++) scanf("%s",s[i]+1);
32     g[0][0]=0;
33     for(int i=1;i<=r;i++){
34         int len=strlen(s[i]+1),lea=strlen(s[i-1]+1);
35         for(int j=1;j<=c;j++){
36             la=cur,cur^=1;g[cur].clear();
37             for(int k=1;k<=g[la].tot;k++){
38                 int v=g[la].val[k],f=g[la].f[k],c1=count(v,j-1),c2=lea-count2(v,j)+1;
39                 if(len-c1>c-j+1)continue;
40                 if((v&(1<<j-1))&&(v&(1<<j))&&c1<len) g[cur][v]=max(g[cur][v],f+(s[i][c1+1]==s[i][c1])+(s[i-1][c2]==s[i][c1+1]));
41                 else if(v&(1<<j-1)&&c1<len) g[cur][v|(1<<j)]=max(g[cur][v|(1<<j)],f+(s[i][c1+1]==s[i][c1]));
42                 else if(v&(1<<j)&&c1<len) g[cur][v]=max(g[cur][v],f+(s[i][c1+1]==s[i-1][c2]));
43                 else if(c1<len) g[cur][v|(1<<j)]=max(g[cur][v|(1<<j)],f);
44                 if(len-c1<=c-j)g[cur][(v|(1<<j))^(1<<j)]=max(g[cur][(v|(1<<j))^(1<<j)],f);
45             }
46         }
47     }
48     for(int i=1;i<=g[cur].tot;i++)
49         if(count(g[cur].val[i],c)==strlen(s[r]+1))
50             ans=max(ans,g[cur].f[i]);
51     printf("%d\n",ans<<1);
52     return 0;
53 }

 

Guess you like

Origin www.cnblogs.com/hzoi-cbx/p/11566865.html