zoukankan      html  css  js  c++  java
  • HDU4689Derangement (动态规划)

    题目链接:传送门 

    题意:

    对于一个由1~n组成的长度为n的序列来说它有n!种排法。我们定义初始的排列为1,2,3,...,n对于兴许的排列假设a[i]>i则用'+'表示。a[i]<i用'-'表示,给定一个长度为n的由'+'与'-'组成的字符串,问满足这个条件的排列有多少种。

    分析:

    设dp[i][j]表示前i个字符中有j个'+'没有排,'-'排完了的方案数。

    那么我们能够依据字符的正负分成两种情况来考虑。

    1.a[i]='+':那么一种情况就是前面有j-1个加号没有放,并且这个加号也不放。或者前面已经有j个加号没有放。那么我们这个加号假设也不放的话就要把这个数放在前面j个加号没有放的位置上,有j种可能。

    因此这时dp[i][j]=dp[i-1][j-1]+dp[i-1][j]*j.

    2.a[i]='-':相同的一种情况就是前面已经有j+1个加号,我们须要把前面这个数放在前面的加号没有放的位置,又要从前面加号没有放的位置选一个放在这个位置一共j*j种方案。另一种是假设前面有j个加号没有放的话我们就仅仅须要从这j个数种选一个放在这个位置上就可以。,因此此时dp[i][j]=dp[i-1][j+1]*j*j+dp[i-1][j]*j;


    代码例如以下:

    #include <iostream>
    #include <cstring>
    #include <cstdio>
    #include <algorithm>
    using namespace std;
    
    const int maxn = 30;
    
    typedef long long LL;
    
    LL dp[maxn][maxn];
    
    char s[maxn];
    
    int main()
    {
        while(~scanf("%s",s)){
            int len = strlen(s);
            memset(dp,0,sizeof(dp));
            dp[0][0]=1LL;
            for(int i=1;i<=len;i++){
                if(s[i-1]=='+'){
                    for(int j=1;j<=len;j++){
                        dp[i][j]+=dp[i-1][j-1];
                        dp[i][j]+=dp[i-1][j]*(LL)j;
                    }
                }
                if(s[i-1]=='-'){
                    for(int j=1;j<=len;j++){
                        dp[i][j-1]+=dp[i-1][j]*(LL)j*j;
                        dp[i][j]+=dp[i-1][j]*(LL)j;
                    }
                }
            }
            printf("%I64d
    ",dp[len][0]);
        }
        return 0;
    }
    


  • 相关阅读:
    理解k8s资源限制系列(二):cpu time
    计算机网络 第五章:传输层
    SYN 攻击原理及解决方法
    Lua中 pairs和ipairs的区别
    nginx里的变量,实现简单过滤。
    LVS负载均衡(LVS简介、三种工作模式、十种调度算法)
    Lua中的loadfile、dofile、require详解
    NGINX 上的限流
    shell 输出json格式的内容
    xilinx资源
  • 原文地址:https://www.cnblogs.com/twodog/p/12139984.html
Copyright © 2011-2022 走看看