
典型的代价优先计算dp
难点就在计算代价上。。。
【1】普通dp tle不知道多少个点

#include<cstdio>
#include<cstdlib>
#include<algorithm>
#include<cstring>
using namespace std;
inline int read()
{
int x=0;char c=getchar();
while(c<'0' || c>'9' ) c=getchar();
while(c>='0'&&c<='9' ) x=(x<<3)+(x<<1)+c-'0',c=getchar();
return x;
}
inline void wr(int x)
{
if(x>=10) wr(x/10);
putchar(x%10+'0');
}
int n;
const int N=5e3+3;
char a[N],b[N];
int la,lb,da[N],db[N];
int sum[26],cnt[2][N][26];
int w[N][N];
int f[N][N];
int main()
{
int T;
scanf("%d",&T);
while(T--)
{
memset(cnt,0,sizeof(cnt));
memset(sum,0,sizeof(sum));
la=lb=0;
//pre0
scanf("%s%s",a+1,b+1);
while(a[++la])
da[la]=a[la]-'A',sum[da[la]]++,cnt[0][la][da[la]]++;
while(b[++lb])
db[lb]=b[lb]-'A',sum[db[lb]]++,cnt[1][lb][db[lb]]++;
la--,lb--;
for(int i=1;i<=la;i++)
{
int res=0;
for(int j=0;j<26;j++)
{
cnt[0][i][j]+=cnt[0][i-1][j];
if(cnt[0][i][j] && cnt[0][i][j]!=sum[j] )
res++;
}
w[i][0]=res;
}
for(int i=1;i<=lb;i++)
{
int res=0;
for(int j=0;j<26;j++)
{
cnt[1][i][j]+=cnt[1][i-1][j];
if(cnt[1][i][j] && cnt[1][i][j]!=sum[j] )
res++;
}
w[0][i]=res;
}
//pre1
for(int i=1;i<=la;i++)
for(int j=1;j<=lb;j++)
{
w[i][j]=w[i][j-1];
if(cnt[0][i][db[j]] + cnt[1][j][db[j]] ==sum[db[j]] )
w[i][j]--;
if(!cnt[1][j-1][db[j]] && !cnt[0][i][db[j]] )
w[i][j]++;
}
//work
memset(f,0x3f,sizeof(f));
f[0][0]=0;
for(int j=1;j<=lb;j++) f[0][j]=f[0][j-1]+w[0][j-1];
for(int i=1;i<=la;i++)
{
f[i][0]=f[i-1][0]+w[i-1][0];
for(int j=1;j<=lb;j++)
f[i][j]=min(f[i][j-1]+w[i][j-1],f[i-1][j]+w[i-1][j] ),
printf("%d ",f[i][j]);
printf("\n");
}
wr(f[la][lb]),putchar('\n');
}
return 0;
}
【2】滚动数组优化 时间和空间

#include<cstdio>
#include<cstdlib>
#include<algorithm>
#include<cstring>
using namespace std;
inline int read()
{
int x=0;char c=getchar();
while(c<'0' || c>'9' ) c=getchar();
while(c>='0'&&c<='9' ) x=(x<<3)+(x<<1)+c-'0',c=getchar();
return x;
}
inline void wr(int x)
{
if(x>=10) wr(x/10);
putchar(x%10+'0');
}
int n;
const int N=5e3+3;
char a[N],b[N];
int la,lb,da[N],db[N];
int sum[26],cnt[2][N][26];
int w[2][N];
int f[2][N];
int main()
{
int T;
scanf("%d",&T);
while(T--)
{
memset(cnt,0,sizeof(cnt));
memset(sum,0,sizeof(sum));
memset(f,0x3f,sizeof(f));
la=lb=0;
//pre0
scanf("%s%s",a+1,b+1);
while(a[++la])
da[la]=a[la]-'A',sum[da[la]]++,cnt[0][la][da[la]]++;
while(b[++lb])
db[lb]=b[lb]-'A',sum[db[lb]]++,cnt[1][lb][db[lb]]++;
la--,lb--;
for(int i=1;i<=la;i++)
for(int j=0;j<26;j++) cnt[0][i][j]+=cnt[0][i-1][j];
for(int i=1;i<=lb;i++)
for(int j=0;j<26;j++) cnt[1][i][j]+=cnt[1][i-1][j];
f[0][0]=w[0][0]=0;
for(int i=1;i<=lb;i++)
{
w[0][i]=w[0][i-1];
if(!cnt[1][i-1][db[i]] ) w[0][i]++;
if( cnt[1][i][db[i]] == sum[db[i]] ) w[0][i]--;
f[0][i]=f[0][i-1]+w[0][i-1];
}
for(int i=1;i<=la;i++)
{
int nw=i&1,pre=nw^1;
//pre1
w[nw][0]=w[pre][0];//对应w[i][0]
if(cnt[0][i][da[i]] == sum[da[i]]) w[nw][0]--;
if(cnt[0][i-1][da[i]] == 0 ) w[nw][0]++;
for(int j=1;j<=lb;j++)//对应w[i][j]
{
w[nw][j]=w[nw][j-1];
if(cnt[0][i][db[j]] + cnt[1][j][db[j]] ==sum[db[j]] ) w[nw][j]--;
if(!cnt[1][j-1][db[j]] && !cnt[0][i][db[j]] ) w[nw][j]++;
}
//work
f[nw][0]=f[pre][0]+w[pre][0];
for(int j=1;j<=lb;j++)
f[nw][j]=min(f[pre][j]+w[pre][j],f[nw][j-1]+w[nw][j-1]);
}
wr(f[la&1][lb]),putchar('\n');
}
return 0;
}
