UVA1625 Color Length (线性DP)
类似于LCS问题,可以用dp[i][j]来表示已选择序列1前i项和序列2前j项的最小目标函数值L( c )。显然,dp[0][0]=0;
因为在选序列1第i个项的前提是前i-1个项必须被选择,序列2同理。
所以dp[i][j]仅可能从dp[i-1][j]和dp[i][j-1]两种状态转移而来。
对目标函数的处理,借鉴紫书上的方法:当把一个元素放到最终序列的时候,递增“已经出现但还未结束”的颜色的L( c )值。
最初的想法是在每次状态转移的时候计算目标函数增加值,对26个字母逐一判断是否出现在最终序列且还未选择完,结果TLE。
参考了他人的想法,先预处理好已选了序列1前i个,序列2前j个时,需要进行递增的数目,用cnt[i][j]表示。
显然,当i!=0且j!=0是,cnt[i][j]可以由cnt[i-1][j]或者cnt[i][j-1]得到。
例如,从cnt[i-1][j]递推,对序列1的第i项进行判断.
如果它是第一次出现在最终序列内且后续还会出现,则cnt[i][j]=cnt[i-1][j]+1;
如果它是最后一次出现在最终序列里,则cnt[i][j]=cnt[i-1][j]-1;这样的判别方法,同时也考虑到只出现一次的颜色。
显然,当i=0时,cnt[i][j]只能从cnt[i][j-1]得来;当j=0时,cnt[i][j]只能从cnt[i-1][j]得来。
我们可以将元素的start值初始化为INF,把元素的end值初始化为-1或0,简化判断过程。
所以,通过上述讨论,可得状态转移方程
1、dp[i][j]=dp[i-1][j]+cnt[i-1][j] (j=0)
2、dp[i][j]=dp[i][j-1]+cnt[i][j-1] (i=0)
3、dp[i][j]=min(dp[i-1][j]+cnt[i-1][j],dp[i][j-1]+cnt[i][j-1] ) (i!=0且j!=0)
预处理的时间复杂度O(nm),dp的时间复杂度O(nm)
#include<bits/stdc++.h>
using namespace std;
const int max_n=5e3+5;
const int INF=0x3f3f3f3f;
string s1,s2;
int n,m;
int dp[max_n][max_n];
int cnt[max_n][max_n];
int start_1[26];
int end_1[26];
int start_2[26];
int end_2[26];
void solve(void)
{
memset(start_1,0x3f,sizeof(start_1));
memset(start_2,0x3f