$Poj1934\\ Trip$ 线性$DP+$搜索

匿名 (未验证) 提交于 2019-12-02 23:51:01

Luogu

Description

爱丽丝和鲍伯想去度假,他们每个人都制定了一个参观城市的清单,该地区正好有26个城市,因此它们被编码为小写字母“a”到“z”.清单上可能重复出现某个城市.因为他们想一起旅行,他们必须走同样的路线.他们不想增加城市或改变城市顺序,所以只能从名单上删除一些城市.他们想尽可能多地参观城市.请你将他们两人的清单合成一个清单.

Input

输入的第一行包含一个整数,表示测试用例数T(T<=10).每个测试用例有两行:第一行是爱丽丝的列表,第二行是鲍伯的列表.每个列表包含1到80个小写字母.

Output

输出所有符合条件的清单,数据保证至少有一种可能的次序,但不超过1000次,按字典序输出.每个测试用例后输出一个空行.

Sol

这题的重点才不是DP,是搜索鸭QwQ. So DP求LCS就不讲了

这里要记录所有长度为ans的序列并按照字典序输出

注意到n的范围较小(1,80),所以是可以用枚举+搜索的

怎么搜呢,用到两个辅助数组,a,b

a[i][j]表示在序列1的前1到j位中,(i+'a'-1)这个字母出现的最大下标

b[i][j]表示在序列2............(同上)

dfs中就只要记录(l1,l2,l,s)表示当前序列1的长度为l1,序列2的长度为l2,待枚举的字母数是l,已经有的字符串s(就是前面枚举的字母形成的字符串鸭)

由于我是字符串白纸,所以get了关于字符串的新技能!

strint s;

s='c'+s; //s="cab"

觉得好方便QwQ

Code

调了半个小时就因为把1写成i了 5555

 1 #include<iostream>  2 #include<cstdio>  3 #include<string>  4 #include<cstring>  5 #include<algorithm>  6 #define Rg register  7 #define il inline  8 #define db double  9 #define ll long long 10 #define mem(a,b) memset(a,b,sizeof(a)) 11 #define go(i,a,b) for(Rg int i=a;i<=b;++i) 12 #define yes(i,a,b) for(Rg int i=a;i>=b;--i) 13 using namespace std; 14 il int read() 15 { 16     int x=0,y=1;char c=getchar(); 17     while(c<'0'||c>'9'){if(c=='-')y=-1;c=getchar();} 18     while(c>='0'&&c<='9'){x=(x<<3)+(x<<1)+c-'0';c=getchar();} 19     return x*y; 20 } 21 int T,ls1,ls2,ct,a[27][81],b[27][81],f[81][81]; 22 string s1,s2,d[1001]; 23 il void init() 24 { 25     mem(f,0);ct=0; 26     go(i,1,26) 27         go(j,1,ls1) 28         if(s1[j]==i+'a'-1)a[i][j]=j; 29         else a[i][j]=a[i][j-1]; 30     go(i,1,26) 31         go(j,1,ls2) 32         if(s2[j]==i+'a'-1)b[i][j]=j; 33         else b[i][j]=b[i][j-1]; 34 } 35 il void dfs(int l1,int l2,int l,string s) 36 { 37     if(l==0){d[++ct]=s;return;} 38     if(l1<1 || l2<1)return; 39     go(i,1,26) 40     { 41         int t1=a[i][l1],t2=b[i][l2]; 42         if(f[t1][t2]==l){dfs(t1-1,t2-1,l-1,char(i+'a'-1)+s);} 43     } 44      45 } 46 int main() 47 { 48     T=read();//remember to init ! ! ! 49     while(T--) 50     { 51         cin>>s1>>s2; 52         ls1=s1.length();ls2=s2.length(); 53         yes(i,ls1,1)s1[i]=s1[i-1]; 54         yes(i,ls2,1)s2[i]=s2[i-1]; 55         init(); 56         go(i,1,ls1) 57             go(j,1,ls2) 58             if(s1[i]==s2[j])f[i][j]=f[i-1][j-1]+1; 59             else f[i][j]=max(f[i-1][j],f[i][j-1]); 60         dfs(ls1,ls2,f[ls1][ls2],""); 61         sort(d+1,d+ct+1); 62         go(i,1,ct)cout<<d[i]<<endl; 63     } 64     return 0; 65 }
View Code

Luogu

Description

爱丽丝和鲍伯想去度假,他们每个人都制定了一个参观城市的清单,该地区正好有26个城市,因此它们被编码为小写字母“a”到“z”.清单上可能重复出现某个城市.因为他们想一起旅行,他们必须走同样的路线.他们不想增加城市或改变城市顺序,所以只能从名单上删除一些城市.他们想尽可能多地参观城市.请你将他们两人的清单合成一个清单.

Input

输入的第一行包含一个整数,表示测试用例数T(T<=10).每个测试用例有两行:第一行是爱丽丝的列表,第二行是鲍伯的列表.每个列表包含1到80个小写字母.

Output

输出所有符合条件的清单,数据保证至少有一种可能的次序,但不超过1000次,按字典序输出.每个测试用例后输出一个空行.

Sol

这题的重点才不是DP,是搜索鸭QwQ. So DP求LCS就不讲了

这里要记录所有长度为ans的序列并按照字典序输出

注意到n的范围较小(1,80),所以是可以用枚举+搜索的

怎么搜呢,用到两个辅助数组,a,b

a[i][j]表示在序列1的前1到j位中,(i+'a'-1)这个字母出现的最大下标

b[i][j]表示在序列2............(同上)

dfs中就只要记录(l1,l2,l,s)表示当前序列1的长度为l1,序列2的长度为l2,待枚举的字母数是l,已经有的字符串s(就是前面枚举的字母形成的字符串鸭)

由于我是字符串白纸,所以get了关于字符串的新技能!

strint s;

s='c'+s; //s="cab"

觉得好方便QwQ

Code

调了半个小时就因为把1写成i了 5555

 1 #include<iostream>  2 #include<cstdio>  3 #include<string>  4 #include<cstring>  5 #include<algorithm>  6 #define Rg register  7 #define il inline  8 #define db double  9 #define ll long long 10 #define mem(a,b) memset(a,b,sizeof(a)) 11 #define go(i,a,b) for(Rg int i=a;i<=b;++i) 12 #define yes(i,a,b) for(Rg int i=a;i>=b;--i) 13 using namespace std; 14 il int read() 15 { 16     int x=0,y=1;char c=getchar(); 17     while(c<'0'||c>'9'){if(c=='-')y=-1;c=getchar();} 18     while(c>='0'&&c<='9'){x=(x<<3)+(x<<1)+c-'0';c=getchar();} 19     return x*y; 20 } 21 int T,ls1,ls2,ct,a[27][81],b[27][81],f[81][81]; 22 string s1,s2,d[1001]; 23 il void init() 24 { 25     mem(f,0);ct=0; 26     go(i,1,26) 27         go(j,1,ls1) 28         if(s1[j]==i+'a'-1)a[i][j]=j; 29         else a[i][j]=a[i][j-1]; 30     go(i,1,26) 31         go(j,1,ls2) 32         if(s2[j]==i+'a'-1)b[i][j]=j; 33         else b[i][j]=b[i][j-1]; 34 } 35 il void dfs(int l1,int l2,int l,string s) 36 { 37     if(l==0){d[++ct]=s;return;} 38     if(l1<1 || l2<1)return; 39     go(i,1,26) 40     { 41         int t1=a[i][l1],t2=b[i][l2]; 42         if(f[t1][t2]==l){dfs(t1-1,t2-1,l-1,char(i+'a'-1)+s);} 43     } 44      45 } 46 int main() 47 { 48     T=read();//remember to init ! ! ! 49     while(T--) 50     { 51         cin>>s1>>s2; 52         ls1=s1.length();ls2=s2.length(); 53         yes(i,ls1,1)s1[i]=s1[i-1]; 54         yes(i,ls2,1)s2[i]=s2[i-1]; 55         init(); 56         go(i,1,ls1) 57             go(j,1,ls2) 58             if(s1[i]==s2[j])f[i][j]=f[i-1][j-1]+1; 59             else f[i][j]=max(f[i-1][j],f[i][j-1]); 60         dfs(ls1,ls2,f[ls1][ls2],""); 61         sort(d+1,d+ct+1); 62         go(i,1,ct)cout<<d[i]<<endl; 63     } 64     return 0; 65 }
View Code

标签
易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!