蓝桥杯2020第十一届国赛_本质上升序列(动态规划_上升子序列)

蓝桥杯2020第十一届国赛_本质上升序列(动态规划_上升子序列)

题目描述
本题为填空题,只需要算出结果后,在代码中使用输出语句将所填结果输出即可。
小蓝特别喜欢单调递增的事物。
在一个字符串中,如果取出若干个字符,将这些字符按照在字符串中的顺序排列后是单调递增的,则成为这个字符串中的一个单调递增子序列。
例如,在字符串 lanqiao 中,如果取出字符 n 和 q,则 nq 组成一个单调递增子序列。类似的单调递增子序列还有 lnq、i、ano 等等。 小蓝发现,有些子序列虽然位置不同,但是字符序列是一样的,例如取第二个字符和最后一个字符可以取到 ao,取最后两个字符也可以取到 ao。小蓝认为他们并没有本质不同。
对于一个字符串,小蓝想知道,本质不同的递增子序列有多少个? 例如,对于字符串 lanqiao,本质不同的递增子序列有 21 个。它们分别是 l、a、n、q、i、o、ln、an、lq、aq、nq、ai、lo、ao、no、io、lnq、anq、lno、ano、aio。
请问对于以下字符串(共 200 个小写英文字母,分四行显示):
tocyjkdzcieoiodfpbgcncsrjbhmugdnojjddhllnofawllbhf
iadgdcdjstemphmnjihecoapdjjrprrqnhgccevdarufmliqij
gihhfgdcmxvicfauachlifhafpdccfseflcdgjncadfclvfmad
vrnaaahahndsikzssoywakgnfjjaihtniptwoulxbaeqkqhfwl
本质不同的递增子序列有多少个?

本题采用动态规划解决。

确定dp数组含义

dp[i]:以s[i]结尾的本质不同递增子序列数。(包括s[i]本身)

确定递推公式

如果s[j] < s[i],两者能构成递增序列,dp[i] += dp[j]

如果s[j] == s[i],我们要去除重复计算的看似不同,本质相同的序列,dp[i] -= dp[j]

确定遍历顺序

从左到右

代码实现

#include 
using namespace std;
typedef long long ll;

int main(void) {
    string s = "tocyjkdzcieoiodfpbgcncsrjbhmugdnojjddhllnofawllbhfiadgdcdjstemphmnjihecoapdjjrprrqnhgccevdarufmliqijgihhfgdcmxvicfauachlifhafpdccfseflcdgjncadfclvfmadvrnaaahahndsikzssoywakgnfjjaihtniptwoulxbaeqkqhfwl";
    vector<ll> dp(s.size(), 1);
    ll res = 1;
    for (int i = 1; i < s.size(); ++i) {
        for (int j = 0; j < i; ++j) {
            if (s[j] < s[i]) dp[i] += dp[j];
            else if (s[j] == s[i]) dp[i] -= dp[j];
        }
        res += dp[i];
    }
    cout << res;
    // system("pause");
    return 0;
}

你可能感兴趣的:(刷题之路,动态规划,蓝桥杯,算法)