【算法竞赛入门经典】类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; }
结果
相关文章推荐
- 【算法竞赛入门经典】递归结构的动态规划 例题9-10 UVa1626
- 【算法竞赛入门经典】集合的动态规划;时间优化 例题9-16 UVa1252
- 【算法竞赛入门经典】DAG上的动态规划 例题9-2 UVa437
- 【算法竞赛入门经典】DAG上的动态规划 例题9-3 UVa1347
- 【算法竞赛入门经典】类似于最优矩阵链乘的动态规划 例题9-9 UVa10003
- 【算法竞赛入门经典】集合的动态规划;位运算 例题9-15 UVa10817
- 【算法竞赛入门经典】DAG上的动态规划 例题9-1 UVa1025
- 【算法竞赛入门经典】7.5 路径寻找问题 例题7-9 UVa1601(1)
- 【算法竞赛入门经典】动态规划初步 例题9-6 UVa11400
- 【算法竞赛入门经典】7.7 回溯法求连通块 例题7-14 UVa1602
- 100道动态规划——18 UVA 1336 Fixing the Great Wall 指标函数的分解,刷表法
- 【算法竞赛入门经典】6.4.2用BFS求最短路 例题6-14 UVa816
- 【算法竞赛入门经典】树的最大独立集、树的唯一性问题 例题9-13 UVa1220
- 【算法竞赛入门经典】6.5[图的概念和拓扑序] 例题6-21 UVa506
- 算法竞赛入门经典 第二版 例题11-4 电话圈 Calling Circles uva247
- 【算法竞赛入门经典】回溯法与最优性剪枝条 例题7-6 UVa140
- 【算法竞赛入门经典】树形DP的状态转移方程优化 例题9-14 UVa1218
- UVa 133 算法竞赛入门经典4-3例题(约瑟夫环类型)
- 算法竞赛入门经典第六章例题6-3 Matrix Chain Multiplication UVA - 442
- 算法竞赛入门经典第五章例题5-5 The SetStack Computer UVA - 12096