虽然并没有学多少东西,但忘的也很快,所以打算在不知道该学什么的时候把前面一些空着的题看一看打一打,没学到的学学,忘了的补一补;
p1284
其中需要一些小小的贪心思想,即尽量让每一对匹配对后面的影响最小;
顺着这个思路,就不难想到可以将每一对匹配作为一个单位来做dp,一切都做完之后,就要好好想想如何不超时了
觉得状态转移方程写了并没什么用,自己不用看,别人看不懂,就不贴了;
一个双进程dp,核心思想是如何break(雾);
1 #include<iostream> 2 #include<string> 3 #include<cstring> 4 #include<cstdio> 5 using namespace std; 6 int f[1000][1000]; 7 int a[1000]; 8 int b[1000]; 9 int topa[10000]; 10 int topb[10000]; 11 int aa[1000][1000]; 12 int m,n; 13 void s() 14 { 15 for(int i=1;i<=m;i++) 16 for(int u=1;u<=n;u++) 17 { 18 if(a[i]==b[u]) 19 { 20 aa[i][++topa[i]]=u; 21 } 22 } 23 } 24 int main() 25 { 26 27 cin>>m>>n; 28 for(int i=1;i<=m;i++) 29 cin>>a[i]; 30 for(int i=1;i<=n;i++) 31 cin>>b[i]; 32 for(int i=1;i<=m;i++) 33 for(int j=1;j<=n;j++) 34 { 35 f[i][j]=max(f[i-1][j],f[i][j-1]); 36 int flag=0; 37 int flag1=0; 38 int flag2=0; 39 for(int u=i-1;u>=1;u--) 40 { 41 flag1=0; 42 flag2=0; 43 if(a[i]==a[u])break; 44 if(flag==2)break; 45 if(a[u]==b[j])flag1=j; 46 for(int w=j;w>=1;w--) 47 { 48 if(f[u-1][w-1]<f[i][j])break; 49 if(a[u]==b[w]&&flag1==0)flag=w; 50 if(a[i]==b[w])flag2=w; 51 if(flag1==0||flag2==0)continue; 52 if(flag1>flag2) 53 f[i][j]=f[u-1][w-1]+1,flag=2; 54 } 55 } 56 } 57 cout<<f[m][n]*2<<endl; 58 return 0; 59 }