設f[i][j][k]爲將i~j的字符最終合併成k的答案。轉移時只考慮最後一個字符是由哪段後綴合成的。若是最後合成爲一個字符特殊轉移一下。ios
複雜度看起來是O(n32k),實際常數極小達到O(玄學)。spa
upd:忽然發現根本沒在bzoj上交。bzoj的數據輸入中沒有空格。code
#include<iostream> #include<cstdio> #include<cmath> #include<cstdlib> #include<cstring> #include<algorithm> using namespace std; int read() { int x=0,f=1;char c=getchar(); while (c<'0'||c>'9') {if (c=='-') f=-1;c=getchar();} while (c>='0'&&c<='9') x=(x<<1)+(x<<3)+(c^48),c=getchar(); return x*f; } #define N 310 int n,m,a[N],c[N],w[N],len[N]; long long f[N][N][N]; int main() { #ifndef ONLINE_JUDGE freopen("bzoj4565.in","r",stdin); freopen("bzoj4565.out","w",stdout); const char LL[]="%I64d\n"; #else const char LL[]="%lld\n"; #endif n=read(),m=read(); memset(f,200,sizeof(f)); for (int i=1;i<=n;i++) a[i]=read(),f[i][i][a[i]]=0,len[i]=(i-1)%(m-1)+1; for (int i=0;i<(1<<m);i++) c[i]=read(),w[i]=read(); for (int k=2;k<=n;k++) for (int i=1;i<=n-k+1;i++) { int j=i+k-1; for (int d=j-1;d>=i;d-=m-1) if (len[k]!=1) for (int v=0;v<(1<<len[k]);v++) f[i][j][v]=max(f[i][j][v],f[i][d][v>>1]+f[d+1][j][v&1]); else for (int u=0;u<(1<<m-1);u++) f[i][j][c[u<<1]]=max(f[i][j][c[u<<1]],f[i][d][u]+f[d+1][j][0]+w[u<<1]), f[i][j][c[u<<1|1]]=max(f[i][j][c[u<<1|1]],f[i][d][u]+f[d+1][j][1]+w[u<<1|1]); } for (int i=1;i<(1<<m);i++) f[1][n][0]=max(f[1][n][0],f[1][n][i]); cout<<f[1][n][0]; return 0; }