UVA - 1625 Color Length

Color Length

\(problem:\)

给出两个颜色序列,长度分别为N,M,现在要将它们合并成一个新序列,每次可以将把一个序列的开头颜色放入新序列的尾部
记st(c)表示新序列中颜色c第一次出现的位置,ed(c)表示新序列中颜色c最后一次出现的位置
记L(c)=ed(c)-st(c),现在要最小化\(\sum_{c}L(c)\)

\(data\) \(range:\)

\(N,M<=5*10^3\)

\(solution:\)

太菜了,看了题解才明白神仙做法
考虑到这题是一个dp
根据套路记\(dp_{i,j}\)表示第一个序列已经将i个元素加入新序列,第二个序列已经将j个元素加入新序列时的最小代价
然后发现,,怎么转移??!!
那么我们再记\(cost_{i,j}\)表示此时的还没有结束的颜色的数量(就是这个颜色不是第一个也不是最后一个)
那么就有转移方程:
\(dp_{i,j}=min(dp_{i-1,j}+cost_{i-1,j},dp_{i,j-1}+cost_{i,j-1})\)
最后一步:如何求出\(cost_{i,j}\)
可以预处理每个颜色分别在两个序列(分别设为a,b)中第一次和最后一次出现的位置
我们考虑\(cost_{i,j-1}->cost_{i,j}(cost_{i-1,j}->cost_{i,j}同理)\)
如果b_j是这个颜色在b中第一次出现的时候,倘若此时a还没有加入这个颜色,那么\(cost_{i,j}=cost_{i,j-1}+1\)
如果b_j是这个颜色在b中最后一次出现的时候,倘若此时a已经加完了这种颜色,那么\(cost_{i,j}=cost_{i,j-1}-1\)

\(space\) \(time\) \(complexity:\)

\(space\)&\(time:\) \(O(n*m)\)

\(note:\)

数组初始化又写炸了啊啊啊

\(code:\)

#include<bits/stdc++.h>
using namespace std;
const int N=5e3+5,Z=30;
int t,lena,lenb,sta[Z],eda[Z],stb[Z],edb[Z];
int dp[N][N],cost[N][N];
char a[N],b[N];
inline void pre()
{
	for(int i=0;i<=lena;++i)
		for(int j=0;j<=lenb;++j)
			dp[i][j]=1e9,cost[i][j]=0;
	fill(sta,sta+Z,lena+1),fill(eda,eda+Z,-1),
	fill(stb,stb+Z,lenb+1),fill(edb,edb+Z,-1);
}
int main()
{
	scanf("%d",&t);
	while(t--)
	{
		scanf("%s%s",a+1,b+1);
		lena=strlen(a+1),lenb=strlen(b+1);
		pre();
		for(char ch='A';ch<='Z';++ch)
		{
			for(int i=1;i<=lena;++i)
				if(a[i]==ch){sta[ch-'A']=i;break;}
			for(int i=lena;i>=1;--i)
				if(a[i]==ch){eda[ch-'A']=i;break;}
			for(int i=1;i<=lenb;++i)
				if(b[i]==ch){stb[ch-'A']=i;break;}
			for(int i=lenb;i>=1;--i)
				if(b[i]==ch){edb[ch-'A']=i;break;}
		}
		dp[0][0]=cost[0][0]=0;
		for(int i=0;i<=lena;++i)
			for(int j=0;j<=lenb;++j)
			{
				if(!i&&!j)continue; 
				int c1=a[i]-'A',c2=b[j]-'A';
				if(i)
				{
					cost[i][j]=cost[i-1][j];
					dp[i][j]=min(dp[i-1][j]+cost[i-1][j],dp[i][j]);
					if(i==sta[c1]&&j<stb[c1])++cost[i][j];
					if(i==eda[c1]&&j>=edb[c1])--cost[i][j];
				}
				if(j)
				{
					cost[i][j]=cost[i][j-1];
					dp[i][j]=min(dp[i][j-1]+cost[i][j-1],dp[i][j]);
					if(i<sta[c2]&&j==stb[c2])++cost[i][j];
					if(i>=eda[c2]&&j==edb[c2])--cost[i][j];
				}
			}
		printf("%d\n",dp[lena][lenb]);
	}
	return 0;
}
posted @ 2020-09-28 15:45  BILL666  阅读(154)  评论(0编辑  收藏  举报