gym 102001 J. Future Generation

14 篇文章 0 订阅

题意:给你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();
}

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值