程序師世界是廣大編程愛好者互助、分享、學習的平台,程序師世界有你更精彩!
首頁
編程語言
C語言|JAVA編程
Python編程
網頁編程
ASP編程|PHP編程
JSP編程
數據庫知識
MYSQL數據庫|SqlServer數據庫
Oracle數據庫|DB2數據庫
 程式師世界 >> 編程語言 >> C語言 >> C++ >> C++入門知識 >> Uva 6177 The Kings Ups and Downs

Uva 6177 The Kings Ups and Downs

編輯:C++入門知識

題意是求1-n 的全排列中有多少呈現高低高低高低或者地高低高形式排列的個數。

這種排列叫做:alternating permutations 或者 Extremal Permutations 。

可以用DP做。

dp(n,k)表示:長度為n,最後一個數為k,最後兩個數是遞增的  排列的個數;

dp2(n,k)表示:長度為n,最後一個數為k,最後兩個數是遞減的 排列的個數;

那麼:

dp(n,k) = dp2(n,n+1-k) ;

很好理解吧,比如說132(低高低)等價於312(高低高),相對的位置加起來等於4.

那麼我們針對dp[n][k]的最後一位進行如下考慮:

最後一位是k,因為dp[n][k]最後兩個數字是遞增的,所以第n-1位的最大值是k-1。那麼我們很容易推導出DP方程:

 \
 


又:

 

\

所以:dp(n,k) = dp(n-1,n+1-k) + dp(n,k-1);

邊界條件略。

代碼:


[cpp]
#include <iostream>  
#include <stdio.h>  
#include <string.h>  
#include <stdlib.h>  
using namespace std; 
 
#define Maxn 25  
#define LL long long  
LL dp[Maxn][Maxn]; 
LL ans[Maxn]; 
 
 
void init() 

    memset(dp,0,sizeof(dp)); 
    memset(ans,0,sizeof(ans)); 
    dp[1][1] = 1; 
    ans[1] = 1; 
    for(int i=2;i<=20;i++) 
    { 
        for(int k=2;k<=i;k++) 
        { 
            dp[i][k] = dp[i-1][i+1-k] + dp[i][k-1]; 
            ans[i] += dp[i][k]; 
        } 
        ans[i] *=2; 
        //printf("%lld\n",ans[i]);  
    } 

int main() 

#ifndef ONLINE_JUDGE  
    freopen("in.txt","r",stdin); 
#endif  
    init(); 
    int p; 
    int m,n; 
    scanf(" %d",&p); 
    while(p--) 
    { 
        scanf(" %d %d",&m,&n); 
        printf("%d %lld\n",m,ans[n]); 
    } 
    return 0; 

  1. 上一頁:
  2. 下一頁:
Copyright © 程式師世界 All Rights Reserved