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; 
    }
  • 相关阅读:
    poj 2485 Highways 最小生成树
    hdu 3415 Max Sum of MaxKsubsequence
    poj 3026 Borg Maze
    poj 2823 Sliding Window 单调队列
    poj 1258 AgriNet
    hdu 1045 Fire Net (二分图匹配)
    poj 1789 Truck History MST(最小生成树)
    fafu 1181 割点
    减肥瘦身健康秘方
    人生的问题
  • 原文地址:https://www.cnblogs.com/yifeiWa/p/11412164.html
Copyright © 2011-2022 走看看