zoukankan      html  css  js  c++  java
  • UVa1638数学递推

      题意不说,直接上思路:

      这道题看起来没有思路,不清楚如何安排能够保证左边l根,右边r根,所以需要简化这道题,让思路浮现出来,

      我们摆放顺序不能是从左到右或者从右到左的顺序摆放,而从小到大不行,所以是从大到小可以,原因是摆放小的不会影响大的,

      将小的摆放左边一定能够使左边+1,同理右边也是一样,而中间则不能对左右造成影响,而从小到大的顺序会对左右产生影响,

      并且不能够很清楚的知道影响了多少(想一想,为什么)。

      所以根据上面定义了状态d(i,j,k)表示从大到小前i个,左边为j,右边为k的方案数,不难想出状态方程:

      放在左边:d(i,j,k) += d(i-1,j-1,k)

      右边: d(i,j,k) += d(i-1,j,k-1)

      中间: d(i,j,k) += d(i-1,j,k)*(i-2)

      所以总的转移方程为: d(i,j,k) = d(i-1,j-1,k) + d(i-1,j,k-1) + d(i-1,j,k)*(i-2)

      代码如下:

    // UVa 1638
    #include <cstdio> 
    #include <cstring> 
    using namespace std; 
    
    const int maxn = 20; 
    
    long long d[maxn+1][maxn+1][maxn+1]; 
    
    void init() {
      memset(d, 0, sizeof(d)); 
      d[1][1][1] = 1;
      for (int i = 2; i <= maxn; ++i) 
        for (int j = 1; j <= i; ++j) 
          for (int k = 1; k <= i; ++k) {
            d[i][j][k] = d[i-1][j][k] * (i - 2);  
            if (j > 1) d[i][j][k] += d[i-1][j-1][k]; 
            if (k > 1) d[i][j][k] += d[i-1][j][k-1]; 
          }
    }
    
    int main() { 
      init(); 
      int T, n, l, r;  
      scanf("%d", &T); 
      while (T--) {
        scanf("%d%d%d", &n, &l, &r); 
        printf("%lld
    ", d[n][l][r]); 
      }
      return 0; 
    }
  • 相关阅读:
    listView控件演示程序
    猪悟能淘宝商品下载专家v3版开发手记
    c# WebClient类
    分隔控件splitter演示程序
    C#中SESSIONID的获取
    工具栏toolBar演示程序
    Cookie总结
    C#获取网页源码并且自动判断网页字符集编码
    如何在Google Code上建立私有代码版本库
    iOS应用程序生命周期(前后台切换,应用的各种状态)详解
  • 原文地址:https://www.cnblogs.com/yifeiWa/p/11412164.html
Copyright © 2011-2022 走看看