HDU 4489 (DP递推计数)
2017-07-22 11:08
351 查看
DP 递推计数
题意:这是一道比较神奇的题,很考验思维:有n个高低不同的人,现在需要进行排列,排列一定要满足两种方式
高低高···
低高低···
求出有多少排列方式。
思路:
我们的切入点是第i个人,如果前i-1个人都已经排列好了,那么第i个人只需插入就行,因为任何人排列先后顺序不影响总的结果,我们就认为插入的人高度递增的,那么第i个人的高度是最高的,把他放在两端的情况有dp[i−1] 种,重点是中间的插入情况,第i人放在中间的情况仔细分析之后有一个条件是必须要满足的那就是第i人左边的1~i-1人的排列一定是 ···高低第i人,右边的排列一定是 第i人低高··· ,因为第i人是最高的那么左右的两个人都是低谷,。加入一共有i-1人,第i人现在要插入其左边有j个人,满足上边条件的情况有dp[j−1]>>1 ,,右边有i-1-j个人,满足上述条件的人有 dp[i−1−j]>>1 (因为开始或者结尾时低的人的情况各占总数的一半) 。那么dp[i]+=(dp[j]>>1)∗(dp[i−1−j]>>1)∗C(j,i−1) ,其中C(j,i−1) 意思是从i-1人中选拔出j人在第i人左边的种类数。
注意点:当第i人左边或者右边只有一个人的情况,只需除以依次2即可。
#include <iostream> #include <cstdio> #include <math.h> using namespace std; typedef long long LL; const int maxn = 30; int n; LL dp[maxn]; LL C(int m,int n) { LL ans = 1; int t = m; while(t) { ans *= n; n--; t--; if(ans%m == 0 && m != 0) { ans /= m; m--; } } while(m) { ans /= m; m--; } return ans; } void init() { dp[1] = 1; dp[2] = 2; dp[3] = 4; for(int i = 4;i <= 20; i++) { dp[i] += dp[i-1]; // printf("%d\n",i); for(int j = 1;j < i - 1; j++) { if(j == 1 || i - j - 1 == 1) dp[i] += (dp[j]*dp[i-j-1]>>1)*C(j,i-1); else dp[i] += (dp[j]>>1)*(dp[i-j-1]>>1)*C(j,i-1); } } } int main() { //freopen("in.txt","r",stdin); init(); int tt; scanf("%d",&tt); for(int i = 1;i <= tt; i++) { int ncase; scanf("%d%d",&ncase,&n); printf("%d %I64d\n",ncase,dp ); } return 0; }
相关文章推荐
- The King’s Ups and Downs hdu 4489 (递推dp)
- HDU 5860 Death Sequence (DP 递推)
- HDU 4901 The Romantic Hero 计数DP
- 动态规划(DP计数):HDU 5116 Everlasting L
- HDU 3469 Catching the Thief (博弈 + DP递推)
- HDU 2709 Sumsets(DP递推)
- 计数DP(Zero Escape,HDU 5389)
- hdu 4363 Draw and paint(dp计数,5级)
- hdu1292(递推dp)
- HDU yt13递推1008钥匙计数之一
- hdu--1028--dp||递推||母函数
- [ACM] hdu 3853 LOOPS (概率DP,递推)
- hdu 2047 阿牛的EOF牛肉串(递推,dp)
- hdu 4901 The Romantic Hero 计数dp,位计算
- hdu 5119 (类似于划分数的状态定义) (DP中的计数问题)
- 【递推】【DP】-HDU-1996-汉诺塔⑥
- HDU - 5136(计数dp)
- HDU 4705 Y (树形DP + 计数)
- hdu 4901 The Romantic Hero(计数dp)2014多校训练第4场1005
- HDU 2084 数塔【dp(递推)+(记忆化)】