zoukankan      html  css  js  c++  java
  • HDU 4055 Number String:前缀和优化dp【增长趋势——处理重复选数】

    题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=4055

    题意:

      给你一个由'I', 'D', '?'组成的字符串,长度为n,代表了一个1~n+1的排列中(数字不重复),相邻数字的增长趋势。('I'为增,'D'为减,'?'为未知)

      问你符合条件的数列有多少种。

    题解:

      表示状态:

        dp[i][j] = combinations

        表示长度为i的排列(由1~i组成),末尾为j,这样的排列的个数

      找出答案:

        ans = ∑ dp[n][1 to n]

      如何转移:

        先考虑增长('I')。

        对于dp[i][j],是由dp[i-1][k with k < j]在末尾添加一个j得到的。

        也就是:

          dp[i][j] = ∑ dp[i-1][1 to j-1]

        可是在dp[i-1][k with k < j]的数列中,由可能j已经选过。

        为了处理这种情况,可以想成将原来数列中 >= j的数都+1。

        这样并不影响原数列的增长性,也不影响答案。

        对于'D'和'?'同理:

          D: dp[i][j] = ∑ dp[i-1][j to i-1]

          ?: dp[i][j] = ∑ dp[i-1][1 to i-1]

    AC Code:

     1 // state expression:
     2 // dp[i][j] = combinations
     3 // i: considering ith num
     4 // j: last num
     5 //
     6 // find the answer:
     7 // sigma dp[n][1 to n]
     8 //
     9 // transferring:
    10 // if increase
    11 // dp[i][j] = sigma dp[i-1][1 to j-1]
    12 // if decrease
    13 // dp[i][j] = sigma dp[i-1][j+1 to i-1]
    14 //
    15 // boundary:
    16 // dp[1][1] = 1
    17 // others = 0
    18 #include <iostream>
    19 #include <stdio.h>
    20 #include <string.h>
    21 #define MAX_N 1005
    22 #define MOD 1000000007
    23 
    24 using namespace std;
    25 
    26 int n;
    27 int ans;
    28 int dp[MAX_N][MAX_N];
    29 int sum[MAX_N][MAX_N];
    30 string s;
    31 
    32 int cal_mod(int a)
    33 {
    34     return (a%MOD+MOD)%MOD;
    35 }
    36 
    37 int cal_sum(int i,int x,int y)
    38 {
    39     if(x>y) return 0;
    40     if(x==0) return sum[i][y];
    41     return cal_mod(sum[i][y]-sum[i][x-1]);
    42 }
    43 
    44 void update_sum(int i,int j,int a)
    45 {
    46     if(j==0) sum[i][j]=cal_mod(a);
    47     else sum[i][j]=cal_mod(sum[i][j-1]+a);
    48 }
    49 
    50 void solve()
    51 {
    52     n=s.size()+1;
    53     memset(dp,0,sizeof(dp));
    54     memset(sum,0,sizeof(sum));
    55     dp[1][1]=1;
    56     for(int i=1;i<=n;i++) sum[1][i]=1;
    57     for(int i=2;i<=n;i++)
    58     {
    59         for(int j=1;j<=i;j++)
    60         {
    61             if(s[i-2]=='I') dp[i][j]=cal_sum(i-1,1,j-1);
    62             else if(s[i-2]=='D') dp[i][j]=cal_sum(i-1,j,i-1);
    63             else dp[i][j]=cal_sum(i-1,1,i-1);
    64             update_sum(i,j,dp[i][j]);
    65         }
    66     }
    67     ans=cal_sum(n,1,n);
    68 }
    69 
    70 void print()
    71 {
    72     cout<<ans<<endl;
    73 }
    74 
    75 int main()
    76 {
    77     while(cin>>s)
    78     {
    79         solve();
    80         print();
    81     }
    82 }
  • 相关阅读:
    webmagic使用
    网站文件下载链接
    正则表达式
    JS 页面刷新或重载
    History
    【问题&解决】fonts/fontawesome-webfont.woff2 404 (Not Found)
    ckeditor的使用
    Windows Server 2012 R2 或 2016 无法安装 .Net 3.5.1
    自定义配置文件的读取
    MVC中上传文件大小限制的解决办法
  • 原文地址:https://www.cnblogs.com/Leohh/p/7767044.html
Copyright © 2011-2022 走看看