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; 
    }
  • 相关阅读:
    【Vue】 修饰符sync
    【VUE】vue路由跳转的方式
    【Element】elementui的Cascader 级联选择器,在懒加载的时候数据无法回显的解决方案
    【ES6】利用ES6 Set 将数组去重
    【.NETCORE】Refit 框架
    【.NETCORE】ASP.NET Core SignalR
    【Visual Studio Code】驼峰翻译助手
    VueX(Vue状态管理模式)
    hdmi 随笔
    ad 差分布线 等长布线
  • 原文地址:https://www.cnblogs.com/yifeiWa/p/11412164.html
Copyright © 2011-2022 走看看