zoukankan      html  css  js  c++  java
  • 动态规划——Valid Permutations for DI Sequence

    We are given S, a length n string of characters from the set {'D', 'I'}. (These letters stand for "decreasing" and "increasing".)

    valid permutation is a permutation P[0], P[1], ..., P[n] of integers {0, 1, ..., n}, such that for all i:

    • If S[i] == 'D', then P[i] > P[i+1], and;
    • If S[i] == 'I', then P[i] < P[i+1].

    How many valid permutations are there?  Since the answer may be large, return your answer modulo 10^9 + 7.

    Example 1:

    Input: "DID"
    Output: 5
    Explanation: 
    The 5 valid permutations of (0, 1, 2, 3) are:
    (1, 0, 3, 2)
    (2, 0, 3, 1)
    (2, 1, 3, 0)
    (3, 0, 2, 1)
    (3, 1, 2, 0)

    这道题目出自LeetCode,可以采用动态规划方法来解决

    这篇博客主要是对LeetCode给出的第一种时间复杂度为O(n^3)的动态规划解法进行解释,题目的大意不再具体解释,有点英文基础的查查百度也能知道
    这个题说的是个什么意思。由于采用的是动态规划解法,所以要找出状态和状态转移方程。LeetCode给的那个解法里面把状态dp[i][j]确定为以下的含义:
    我们每次只注重最后一个数字在整个数组序列中 小->大 排列后的位置,如果给数组编号为i = 0、1、...、n,我们关注的焦点dp[i][j]可以解释为长度为i+1的数组中某个方案中
    其最后一个数字即第i个数字在这i+1个数字中处于第j+1小位置的方案的数量,比如dp[0][0]的意义就是长度为长度为1的数组{0}按字符串S的要求下重新排列后的新数组其第0个数字在整个数组中排最小的方案数字,而且易知dp[0][0]=1。
    而且dp[0]只用dp[0][0]这一个元素,其他的用不上,对于每个i = 0、1、...、n,我们只用dp[i][0..i]这些元素。
    状态转移方程的解释更加复杂,如果S[i-1]=='D',递减,则p[i]<p[i-1],这个时候dp[i][j]是所有dp[i-1][j<=k<=i-1]的和,k之所以小于i是因为对于dp[i-1]来说它一共就i个成员,下标访问到i会越界,k大等于j的原因不好解释,
    有一个替换的问题在里面,因为dp[i]比dp[i-1]多一个元素,它们所代表的数组也是前者比后者多一个,由于dp[i]所属的数组方案中按 小->大的数组和dp[i-1]的那个数组中第k(1<=k<=i)个数字是一样的,这里我不知道怎么叙述好,
    反正就是dp[i]所代表的那个长的最后一位可以使用dp[i-1]所代表的那个短的最后一位,因为是递减,可以把dp[i]代表的数组中多出来的那一个最大的数组顶在倒数第二个位置上;如果S[i-1]=='T',由于dp[i]所属的数组方案中按 小->大
    组和dp[i-1]的那个数组中第k(1<=k<=i)个数字是一样的,dp[i][j]是所有dp[i-1][0<=k<j]的和。这个题的思路上确实是比较复杂的,也不是很好叙述清楚它的思路。这个题最后一个注意点就是要求模,记住每次求模即可。

    下面直接上代码:
     1 int numPermsDISequence(string S){
     2     int MOD = 1000000007;
     3     int n = S.length();
     4     int**dp = new int*[n + 1];
     5     for (int i = 0; i <= n; i++)
     6         dp[i] = new int[n + 1];
     7     for (int i = 0; i <= n;i++)
     8     for (int j = 0; j <= n; j++){
     9         if (i == 0)dp[i][j] = 1;
    10         else dp[i][j] = 0;
    11     }
    12     for (int i = 1; i <= n; i++){
    13         for (int j = 0; j <= i; j++){
    14             if (S[i - 1] == 'D'){
    15                 for (int k = j; k < i; k++){
    16                     dp[i][j] += dp[i - 1][k];
    17                     dp[i][j] %= MOD;
    18                 }
    19             }
    20             else{
    21                 for (int k = 0; k < j; k++){
    22                     dp[i][j] += dp[i - 1][k];
    23                     dp[i][j] %= MOD;
    24                 }
    25             }
    26         }
    27     }
    28 
    29     for (int i = 0; i <= n; i++){
    30         for (int j = 0; j <= n; j++)
    31             cout << dp[i][j] << " ";
    32         cout << endl;
    33     }
    34     
    35 
    36     int ans = 0;
    37     for (int i = 0; i <= n; i++){
    38         ans += dp[n][i];
    39         ans %= MOD;
    40     }
    41     for (int i = 0; i <= n; i++)
    42         delete[]dp[i];
    43     delete[]dp;
    44     return ans;
    45 }
    
    
    






  • 相关阅读:
    泛微云桥e-Bridge 目录遍历,任意文件读取
    (CVE-2020-8209)XenMobile-控制台存在任意文件读取漏洞
    selenium 使用初
    将HTML文件转换为MD文件
    Python对word文档进行操作
    使用java安装jar包出错,提示不是有效的JDK java主目录
    Windows server 2012安装VM tools异常解决办法
    ifconfig 命令,改变主机名,改DNS hosts、关闭selinux firewalld netfilter 、防火墙iptables规则
    iostat iotop 查看硬盘的读写、 free 查看内存的命令 、netstat 命令查看网络、tcpdump 命令
    使用w uptime vmstat top sar nload 等命令查看系统负载
  • 原文地址:https://www.cnblogs.com/messi2017/p/9874956.html
Copyright © 2011-2022 走看看