• UVA


    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
    ",dp[lena][lenb]);
    	}
    	return 0;
    }
    
  • 相关阅读:
    [Leetcode] Regular Expression Matching
    [Leetcode] Edit Distance
    计算机科学论文写作3-表、图、例子和其他类似的元素的使用
    计算机科学论文写作2-搜寻、阅读和引用文献
    灰度图与彩图的双边滤波
    opencv6.1-imgproc图像处理模块之平滑与形态学操作
    opencv5-objdetect之级联分类器
    opencv4-highgui之视频的输入和输出以及滚动条
    计算机科学论文写作1-引言
    lecture11-hopfiled网络与玻尔兹曼机
  • 原文地址:https://www.cnblogs.com/zmyzmy/p/13745084.html
Copyright © 2020-2023  润新知