题意:给你n(n<=15)个串(len<=15),找出严格递增的n个子串使其长度之和最大
思路:递推型DP,F[I][J]记录做到第i个串,当前获得的总长度为J,其字典序最小的(第i个串中)子串
#include<bits/stdc++.h>
#include<tr1/unordered_map>
#include<bits/stdc++.h>
#define clr(a,b) memset(a,b,sizeof(a))
#define fpn() freopen("simple.in","r",stdin)
#define rd read()
using namespace std;
const int maxn=2010;
typedef long long ll;
struct node{
char c[20];
int l;
}q[20][40000];
struct nod{
int p=0,l;
char c[20];
}f[20][400];
int len[20],n,flag[20];
char s[20][20],c[20][20];
void work(int x)
{
int l=strlen(s[x]),z=0;
for(int i=1;i<=(1<<l)-1;i++)
{
len[x]++;z=0;
for(int k=0;k<l;k++)
{
if((i&(1<<k))!=0)
{
// printf("i=%d k=%d\n",i,k);
q[x][len[x]].c[++z]=s[x][k];
}
}
q[x][len[x]].l=z;
// printf("x=%d i=%d\n",x,i);
// for(int j=1;j<=z;j++) printf("%c",q[x][len[x]].c[j]);
// printf("\n");
}
}
void init()
{
for(int i=1;i<=n;i++) work(i);
}
int check(int x,int j)
{
for(int i=1;i<=x;i++)
if(f[1][x].c[i]>q[1][j].c[i]) return 1;
else if(f[1][x].c[i]<q[1][j].c[i]) return 0;
return 0;
}
int chec(int i,int j,int k)
{
for(int p=1;p<=min(q[i][k].l,f[i-1][j].l);p++)
if(f[i-1][j].c[p]>q[i][k].c[p]) return 0;
else if(f[i-1][j].c[p]<q[i][k].c[p]) return 1;
if(q[i][k].l>f[i-1][j].l) return 1;
return 0;
}
int chec2(int i,int j,int pq)
{
for(int p=1;p<=min(pq,f[i][j+pq].l);p++)
if(c[pq][p]>f[i][j+pq].c[p]) return 0;
else if(c[pq][p]<f[i][j+pq].c[p]) return 1;
if(pq<f[i][j+pq].l) return 1;
return 0;
}
void dodo()
{
for(int j=1;j<=len[1];j++)
{
int len1=q[1][j].l;
if(f[1][len1].p==0)
{
f[1][len1].p=1;
f[1][len1].l=len1;
for(int k=1;k<=len1;k++) f[1][len1].c[k]=q[1][j].c[k];
}
else{
if(check(len1,j))
{
for(int k=1;k<=len1;k++) f[1][len1].c[k]=q[1][j].c[k];
}
}
}
// for(int i=1;i<=7;i++)
// {
// for(int j=1;j<=f[1][i].l;j++) printf("%c",f[1][i].c[j]);
// printf("\n");
// }
for(int i=2;i<=n;i++)
for(int j=1;j<=16*16;j++)
{
if(f[i-1][j].p!=0)
{
// printf("========%d\n",f[i-1][j].l);
// for(int ii=1;ii<=f[i-1][j].l;ii++) printf("%c",f[i-1][j].c[ii]);
// printf("\n");
for(int i1=1;i1<=16;i1++)
for(int j1=1;j1<=i1;j1++)
c[i1][j1]='z';
for(int i1=1;i1<=16;i1++) flag[i1]=1;
for(int k=1;k<=len[i];k++)
{
int l=q[i][k].l;
if(chec(i,j,k)>0)
// if(strncmp(&(q[i][k].c[1]),&(f[i-1][j].c[1]), l)>0)
{
// printf("%d %d %d\n",i,j,k);
if(strncmp(&(c[l][1]),&(q[i][k].c[1]), l)>0)
{
flag[l]=0;
for(int kk=1;kk<=l;kk++) c[l][kk]=q[i][k].c[kk];
}
}
}
for(int pq=1;pq<=16;pq++)
if(flag[pq]==0)
{
// printf("i=%d j=%d\n",i,j);
// for(int kk=1;kk<=f[i-1][j].l;kk++) printf("%c",f[i-1][j].c[kk]);
// printf("\n");
// for(int kk=1;kk<=pq;kk++) printf("%c",c[pq][kk]);
// printf("\n");
if(f[i][j+pq].p==0)
{
// printf(" %d %d %d\n",i,j,pq);
f[i][j+pq].l=pq;
for(int kk=1;kk<=pq;kk++)
f[i][j+pq].c[kk]=c[pq][kk],f[i][j+pq].p=1;
}
else{
if(chec2(i,j,pq)>0)
{
// printf(" %d %d %d\n",i,j,pq);
for(int kk=1;kk<=pq;kk++)
f[i][j+pq].c[kk]=c[pq][kk],f[i][j+pq].p=1;
f[i][j+pq].l=pq;
}
}
}
}
}
int ans=-1;
for(int i=1;i<=16*16;i++)
if(f[n][i].p!=0) ans=i;
printf("%d\n",ans);
}
int main()
{
scanf("%d",&n);
for(int i=1;i<=n;i++) scanf("%s",s[i]);
init();
dodo();
}