注意每次循环中对d数组的初始化,不需要调用
memeset(d,-1,sizeof(d));
因为d数组申请了maxl=5000+10的空间大小,这个语句在实际执行会很耗时间。而且也并不是d数组所有的空间都需要初始化。只初始化会用到的值足矣。
#include<iostream>
#include<stdio.h>
#include<string.h>
#include<algorithm>
using namespace std;
#define maxn 26+10
#define maxl 5000+10
#define INF 100000000
int l1=0,l2=0;
int sta_1[maxn];
int end_1[maxn];
int sta_2[maxn];
int end_2[maxn];
char s1[maxl],s2[maxl];
int d[maxl][maxl];
int arr[30];
int com[maxl][maxl];
bool judge(int i,int j,int x)//包括i j及 i j右边的元素都没有访问过的情况下,x是否应该导致m加一
{
if(arr[x]==0&&
(sta_1[x]<i||sta_2[x]<j)&&
(end_1[x]>=i||end_2[x]>=j))
{
arr[x]=1; return true;
}
return false;
}
void com_plus()//包括i j及 i j右边的元素都没有访问过
{
for(int i=1;i<=l1+1;i++)
{
for(int j=1;j<=l2+1;j++)
{
int m=0;
memset(arr,0,30*sizeof(int));
for(int k=1;k<i;k++)
{
int x=s1[k]-64;//x是s1第K个元素在ABCD...Z中的序号
if(arr[x]==0&&judge(i,j,x))
m++;
}
for(int k=1;k<j;k++)
{
int x=s2[k]-64;
if(arr[x]==0&&judge(i,j,x))
m++;
}
com[i][j]=m;
}
}
}
int fun(int i,int j)//i j还没入队列
{
if(i>l1&&j>l2)
return 0;
if(d[i][j]!=-1)
return d[i][j];
int temp=INF,temp1=INF,temp2=INF;
if(i<=l1)//i即将后移 此时的i为要入队列 待会调用 fun(i+1,j)
{
temp1=com[i+1][j]+fun(i+1,j);
}
if(j<=l2)
{
temp2=com[i][j+1]+fun(i,j+1);
}
temp=min(temp1,temp2);
d[i][j]=temp;
return d[i][j];
}
int main()
{
int n;
scanf("%d\n",&n);
for(int i=0;i<n;i++)
{
l1=l2=0;
memset(sta_1,0,sizeof(sta_1));
memset(sta_2,0,sizeof(sta_2));
memset(end_1,0,sizeof(end_1));
memset(end_2,0,sizeof(end_2));
char c;
scanf("%c",&c);
while(c!='\n')
{
l1++;
s1[l1]=c;
if(!sta_1[c-64])
sta_1[c-64]=l1;
end_1[c-64]=l1;
scanf("%c",&c);
}
scanf("%c",&c);
while(c!='\n')
{
l2++;
s2[l2]=c;
if(!sta_2[c-64])
sta_2[c-64]=l2;
end_2[c-64]=l2;
scanf("%c",&c);
}
for(int i=1;i<=l1+1;i++)
for(int j=1;j<=l2+1;j++)
d[i][j]=-1;
com_plus();
cout<<fun(1,1)<<endl;
}
}