zoukankan      html  css  js  c++  java
  • HDU 4055 Number String

    Number String

    Time Limit: 5000ms
    Memory Limit: 32768KB
    This problem will be judged on HDU. Original ID: 4055
    64-bit integer IO format: %I64d      Java class name: Main
     
    The signature of a permutation is a string that is computed as follows: for each pair of consecutive elements of the permutation, write down the letter 'I' (increasing) if the second element is greater than the first one, otherwise write down the letter 'D' (decreasing). For example, the signature of the permutation {3,1,2,7,4,6,5} is "DIIDID".

    Your task is as follows: You are given a string describing the signature of many possible permutations, find out how many permutations satisfy this signature.

    Note: For any positive integer n, a permutation of n elements is a sequence of length n that contains each of the integers 1 through n exactly once.
     

    Input

    Each test case consists of a string of 1 to 1000 characters long, containing only the letters 'I', 'D' or '?', representing a permutation signature.

    Each test case occupies exactly one single line, without leading or trailing spaces.

    Proceed to the end of file. The '?' in these strings can be either 'I' or 'D'.
     

    Output

    For each test case, print the number of permutations satisfying the signature on a single line. In case the result is too large, print the remainder modulo 1000000007.
     

    Sample Input

    II
    ID
    DI
    DD
    ?D
    ??

    Sample Output

    1
    2
    2
    1
    3
    6
    Hint
    Permutation {1,2,3} has signature "II". Permutations {1,3,2} and {2,3,1} have signature "ID". Permutations {3,1,2} and {2,1,3} have signature "DI". Permutation {3,2,1} has signature "DD". "?D" can be either "ID" or "DD". "??" gives all possible permutations of length 3.

    Source

     
    解题:动态规划 Regional的题目质量真的很高
     

    题目分析:对于一个n个数排列,用I 表示后一个数比前一个数大, 用D表示后一个数比前一个数小。例如:123 就是II 。312就是DI。?表示可以I 或者D。给I,D,?组成的程度为n的序列,找出这个序列所能表示的全排列的个数,每个数字只能出现一次。

    显然如果序列的长度为n , 则为1 ~ n+1的排列。

    设dp[ i ][ j ] 为 前i - 1 已经排列好 , 第i 位为j的排列数。sigma dp[ n + 1 ][ j ] , j 从1 到n+1 ,为要求的结果。

    如果第i位对应 ‘ I ’ ,则dp[ i ][ j ] = dp[ i - 1][ j - 1] + dp[ i - 1][ j - 2] + …… + dp[ i - 1 ][ 1 ] ;

    考虑第i位时,前面i - 1 位都已经排好,且第i - 1位的数字 小于 j 的排列都可以在第i位放j , 所以可得上式。

    如果第j位对应‘D’ , 则dp[ i ][ j ] = dp[ i - 1][ i - 1] + dp[ i - 1][ i - 2 ] + …… + dp[ i - 1 ][ j ] ;

    对于第 i - 1 位的数字大于等于 j  的排列 , 将前 i - 1 位中大于等于j的数字都加1 ,前面的情况依然成立 , 且第 i 位可以放 j 。

    例如 (1 ,3 , 2) 。第4位对应D , 想放2 。将前三位大于等于2的加1,得到  (1 , 4, 3 )。将2放在后面,得到(1,4,3,2)。  所以第i - 1 位大于等于 j 的都可以入选 , 因为加1之后 , 肯定比 j 大。

    如果第i为对应‘?’ , 则以上两种情况相加。

    用sum[ i ][ j ] 表示 dp[ i ][ j ] + dp[ i ][  j - 1 ] + …… + dp[ i ][ 1 ] 

    则,状态转移可写成:

    对应  I 时 , dp[ i ][ j ] = sum[ i - 1][ j - 1]  

    对应 D时 ,dp[ i ][ j ] = sum[ i - 1][ i - 1] - sum[ i - 1][ j - 1]

    对应 ?时 , dp[ i ][ j ] = sum[ i - 1 ][ i - 1]

    以上内容摘自玻璃年华Alex

     1 #include <bits/stdc++.h>
     2 using namespace std;
     3 typedef long long LL;
     4 const int mod = 1000000007;
     5 const int maxn = 1010;
     6 LL dp[maxn][maxn],sum[maxn][maxn];
     7 char str[maxn];
     8 int main(){
     9     while(~scanf("%s",str)){
    10         int n = strlen(str)+1;
    11         dp[1][1] = sum[1][1] = 1;
    12         for(int i = 2; i <= n; ++i){
    13             for(int j = 1; j <= i; ++j){
    14                 if(str[i - 2] == 'I') dp[i][j] = sum[i - 1][j - 1];
    15                 else if(str[i - 2] == 'D') dp[i][j] = (sum[i-1][i-1] - sum[i-1][j-1] + mod)%mod;
    16                 else dp[i][j] = sum[i-1][i-1];
    17                 sum[i][j] = (sum[i][j-1] + dp[i][j])%mod;
    18             }
    19         }
    20         printf("%I64d
    ",sum[n][n]);
    21     }
    22     return 0;
    23 }
    View Code
  • 相关阅读:
    Filter and Listener
    Cookie Session
    怎样快速将一台电脑虚拟机导入另外一台电脑
    网页下载文件服务端代码
    图片验证码生成代码
    Request实战
    Response
    设置页眉页脚的距离
    页眉页脚的设置
    节的设置
  • 原文地址:https://www.cnblogs.com/crackpotisback/p/4789093.html
Copyright © 2011-2022 走看看