您的位置:首页 > 其它

【算法竞赛入门经典】类LCS动态规划;指标函数分解 例题9-7 UVa1625

2018-03-02 13:09 741 查看

【算法竞赛入门经典】类LCS动态规划;指标函数分解 例题9-7 UVa1625

【算法竞赛入门经典】类LCS动态规划;指标函数分解 例题9-7 UVa1625
例题UVa1625
指标函数

分析

样例实现代码

结果

例题UVa1625





Input



Output



Sample Input

2

AAABBCY

ABBBCDEEY

GBBY

YRRGB

Sample Output

10

12

指标函数

指标函数和最优值函数

指标函数即用来衡量所实现过程优劣的数量指标,它定义在全过程和所有后部子过程上确定的数量函数,用 Vk,n 表示,即 Vk,n = Vk,n(sk, uk, sk+1, uk+1, … , sn+1) , k = 1, 2, …, n。该指标函数应该具有可分离性,并满足递推关系,即Vk,n可以表示为sk,uk,Vk+1,n的函数。常见的指标函数有(1)过程和它的任一子过程的指标是它所包含的各个阶段的指标的和;(2)过程和它的任一子过程的指标是它所包含的各个阶段的指标的乘积。

最优值函数是指标函数的最优值,记为fk(sk),表示从第k阶段的状态开始到第n阶段的终止状态的过程,采取最优策略所得到的指标函数值(一般是最大/最小值),即:



不同的问题中指标函数的含义不同,可能是距离、利润、成本、产量或资源消耗等等。

分析

利用dp[i]表示第一串字符放置i个且第二串字符放置j个之后的当前消耗。

其实状态转移方程比较好写。

dp[i][j]=min(dp[i-1][j]+c(i),dp[i][j-1]+c(j));


c(i)或是c(j)的含义就是当前放置一个字符之后多出的消耗。

但是这个c()函数算起来是非常的不便利,如果每次放置都去重新更新元素的距离跨度是难以接受的。

因此我们尝试简化这个c()函数。

事实上,每次移动一个元素的时候,如果有元素出现了第一个且没有出现最后一个,即该元素没有结束,那么该元素的耗费势必增加。进一步的,我们不需要关心具体是哪个颜色,只要知道有多少个颜色没有结束就可以了。这样每次更新的c()函数可以理解为,没有结束的颜色引起的耗费增加,每一个元素引起的耗费+1

这样用c[i][j]数组进行统计,当插入某个元素时候的耗费。c[i][j]的计算应该也算一个dp的过程,实际上两个dp同时进行了。只不过c[i][j]的更新和某个元素有没有结束有关,方便起见可以提前统计每个颜色的开始结束位置。

除此之外,这里的memset没有必要使用,因为递推从前到后且dp[0][0]不会变,因此memset反而浪费了时间。

样例实现代码

#include<iostream>
#include<cstring>
#include<algorithm>
#define maxn 5000+5
#define INF 1000000
using namespace std;
int dp[maxn][maxn],c[maxn][maxn],stp1[26],stp2[26],enp1[26],enp2[26];
char p1[maxn],p2[maxn];
int main(){
int T;
cin>>T;
while(T--){
//  memset(dp,0,sizeof(dp));
//  memset(c,0,sizeof(c));
//这里的memset没有必要,花费大量时间且无用
scanf("%s%s",p1+1,p2+1);
int n1=strlen(p1+1),n2=strlen(p2+1);
for(int i=1;i<=n1;i++)
p1[i]-='A';
for(int j=1;j<=n2;j++)
p2[j]-='A';
for(int i=0;i<26;i++){
stp1[i]=stp2[i]=maxn;
enp1[i]=enp2[i]=0;
}
for(int i=1;i<=n1;i++){
stp1[p1[i]]=min(stp1[p1[i]],i);
enp1[p1[i]]=i;
}
for(int i=1;i<=n2;i++){
stp2[p2[i]]=min(stp2[p2[i]],i);
enp2[p2[i]]=i;
}
for(int i=0;i<=n1;i++){
for(int j=0;j<=n2;j++){
if(i==0&&j==0)
continue;
int p1v=INF,p2v=INF;
if(i)
p1v=dp[i-1][j]+c[i-1][j];
if(j)
p2v=dp[i][j-1]+c[i][j-1];
dp[i][j]=min(p1v,p2v);
if(dp[i][j]==p1v){
c[i][j]=c[i-1][j];
if(stp1[p1[i]]==i&&stp2[p1[i]]>j)
c[i][j]++;
if(enp1[p1[i]]==i&&enp2[p1[i]]<=j)
c[i][j]--;
}
else{
c[i][j]=c[i][j-1];
if(stp2[p2[j]]==j&&stp1[p2[j]]>i)
c[i][j]++;
if(enp2[p2[j]]==j&&enp1[p2[j]]<=i)
c[i][j]--;
}
}
}
cout<<dp[n1][n2]<<endl;
}
return 0;
}


结果

内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: 
相关文章推荐