uvA1625 color length dp

本文介绍了一种使用动态规划解决颜色匹配问题的方法。通过定义计数器数组c来记录颜色的数量变化,实现对颜色开始和结束状态的有效跟踪。利用预处理和递推公式,解决了两个字符串中颜色匹配的最优化问题。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

对于一个颜色 开始时把他存储到计数器数组c中  

结束时再减去 这样可以直接无视中间的变化过程

c[i][j]表示在str1 的i 位置 str2 的j位置 已经开始遍历但未遍历结束的颜色的数量 是一个递推的过程

可以先预处理

dp很简单 难的时上面的c数组

dp意思时 前一个状态的最优加上未结束的颜色数量

总共俩状态 取最小就是最优

#include<bits/stdc++.h>
#define clr(a,b) memset(a,b,sizeof(a));
#define INF 0x3f3f3f3f
using namespace std;

const int maxn=5010;

int dp[maxn][maxn];
int c[maxn][maxn];
char p[maxn],q[maxn];
int sp[27],ep[27],sq[27],eq[27];

int main()
{
	int t;
	scanf("%d",&t);
	while(t--)
	{
		
		for (int i = 0; i < 26; i++)
        {
            sp[i]=sq[i]=INF;
            ep[i]=eq[i]=0;
        }
		scanf("%s",p+1);
		scanf("%s",q+1);
		int n=strlen(p+1);
		int m=strlen(q+1);
		for(int i=1;i<=n;i++) p[i]-='A';
		for(int i=1;i<=m;i++) q[i]-='A';
		for(int i=1;i<=n;i++)
		{
			sp[p[i]]=min(sp[p[i]],i);
			ep[p[i]]=i;
		}
		for(int i=1;i<=m;i++)
		{
			sq[q[i]]=min(sq[q[i]],i);
			eq[q[i]]=i;
		}
		//for (int i = 0; i < 26; i++)
		//{
		//	cout<<sp[i]<<"  "<<sq[i]<<"  "<<ep[i]<<"  "<<eq[i]<<endl;
		//}
		for(int i=0;i<=n;i++)
		{
			for(int j=0;j<=m;j++)
			{
				if(i)
				{
					c[i][j]=c[i-1][j];
					if(sp[p[i]]==i&&j<sq[p[i]]) c[i][j]++;//j<sq[q[i]]另一个字符串的q[i]没走完 //当p中只有一个颜色时 q还有 那么它就是起点 
					if(ep[p[i]]==i&&j>=eq[p[i]]) c[i][j]--;
				}
				else if(j)//只在i==0时进入 
				{
					c[i][j]=c[i][j-1];
					if(sq[q[j]]==j&&i<sp[q[j]]) c[i][j]++;
					if(eq[q[j]]==j&&i>=ep[q[j]]) c[i][j]--;
				}
			}
		}
		/*for(int i=0;i<=n;i++)
		{
			for(int j=0;j<=m;j++)
			{
				cout<<c[i][j]<<"	";
			}
			cout<<endl;
		}*/
		for(int i=0;i<=n;i++)
		{
			for(int j=0;j<=m;j++)
			{
				if(!i&&!j) continue;
				int v1=INF,v2=INF;
				if(i) v1=dp[i-1][j]+c[i-1][j];
				if(j) v2=dp[i][j-1]+c[i][j-1];
				dp[i][j]=min(v1,v2);
			}
		}
		printf("%d\n",dp[n][m]);
	}
}

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值