今天是释然发题解的第十八天,以后每一天都会和大家分享学习路上的心得,希望和大家一起进步,一起享受coding的乐趣。
本文约1400字,预计阅读5分钟
昨天我们学习了动态规划之背包型规划,忘记的小伙伴们可以看一下哦:
今天我们来聊一聊动态规划的线性规划,明天和大家分享动态规划的相关题目:
例题一:最长公共子序列问题
这道题目呢,在一开始没有学习动态规划之前呢,是一个头疼的问题
但是学习了以后呢,将步骤分解,考虑每一层递推的情况之后,这道题就迎刃而解了:
那么我们依然是三步走:
第一步:dp数组的含义:指的是第一个序列长度为i时,第二个序列长度为j时,
这两段公共子序列的长度
第二步:找递推关系
如果a【i】==b【j】的话呢,dp【i+1】【j+1】=dp【i】【j】+1呀
对于不相等的情况,就应该覆盖之前的最大值即:dp【i+1】【j+1】=max(dp[i+1][j],dp[i][j+1])
第三步:
初始化:当任意一个序列时0时,dp数组就应该是0.最后输出dp[i][j]就可以啦!
int n, m;
char s1[MAX_N + 1], s2[MAX_N + 1];
void solve()
{
for (int i = 0; i < n; i++)
{
for (int j = 0; j < m; j++)
{
if (s1[i] == s2[j])
{
dp[i + 1][j + 1] = dp[i][j] + 1;
}
else
{
dp[i + 1][j + 1] = max(dp[i + 1][j],dp[i][j + 1]);
}
}
}
cout << dp[n][m];
}
例题二:最长上升子序列问题
int n;
int a[MAX_N];
int dp[MAX_N];
void solve()
{
int ans = 0;
for (int i = 0; i < n; i++)
{
dp[i] = 1;
for (int j = 0; j < i; j++)
{
if (a[j] < a[i])
{
dp[i] = max(do[i], dp[j] + 1);
}
}
ans = max(ans, dp[i]);
}
cout << ans;
}
例题三:导弹拦截
很容易想到贪心法:那就是采取多次求最长不上升序列的办法,然后得出总次数。
上述贪心法不正确,很容易就能举出反例。
例如: “7 5 4 1 6 3 2”
用多次求最长不上升序列所有为
“7 5 4 3 2”、“1”、“6”共3套系统;
但其实只要2套,分别为:
“7 5 4 1”与“6 3 2”。
那么,正确的做法又是什么呢?
找最长不上升子序列,得到的序列个数就是答案
for(i=1;i<=n;i++)
dps[i]=1;
for(i=1;i<=n;i++)
{
for(int j=1;j<i;j++)
if(num[i]>num[j])
dps[i]=max(dps[i],dps[j]+1);
ans=max(ans,dp[i];
}
好了,今天的动态规划就到这里。
释然每天发布一点自己学习的知识,希望2年后我们也能在ACM的赛场上见面,一起去追寻自己的程序猿之路吧!
后期也会和大家一起分享学习心得和学习经验呢,明天我们不见不散哦!
下期预告:
动态规划之区间型动态规划
如果大家有什么建议或者要求请后台留言,释然也想和大家一起进步呀!
联系方式:shirandexiaowo@foxmail.com