zoukankan      html  css  js  c++  java
  • 卡特兰数

    一套有趣的题目

    1. 1,2,3…n 以此进栈,求有多少种可能的出栈序列。
    2. 由n对括号形成的合法的括号序列有多少个。
      1. N<=10^5
      2. 这个问题还有很多其他的表达形式。
    3. n个节点共能构成多少种二叉树,左右子树是认为不同。
    4. 凸多边形的三角划分的方案数:把一个凸多边形用n-3条直线连接n-3对顶点,共形成n-2个三角形,求方案数。(n+2边形三角划分)
    5. 一个n*n的格子,从(0,0)走到(n,n),求不跨过(0,0)->(n,n)这条直线的路径方案数

    eg2:设f[i]表示i对括号的方案数,那么有:(f[n]=sumlimits_{i=0}^{n-1}f[i]*f[n-i-1])

    卡特兰数:

    我们设f[n]表示n个数依次进栈所能形成的出栈序列数。

    似乎和之前不一样,好像不是划分成一段一段那样的简单形式。

    我们可以考虑另一种形式的状态转移方式,以转移到子问题。

    注意一段一段划分我们可以枚举最后一段的起点,但是这里不是一段一段的,我们要考虑另外的转移方式。

    实际上我们发现我们可以枚举1这个数是什么时候出栈的。

    那么我们可以得到:(f[n]=sumlimits_{i=0}^{n-1}f[i]*f[n-i-1])

    一个经典题

    有n个数,选择其中若干数,使得每连续k个数中都至少有一个数被选中,且选出的数的和最小。

    k<=n<=1000

    k<=n<=100000

    SOLUTION:

    首先我们定义f[i]表示按照满足题目要求的选择选取,并且第i个数一定被选中的最小和是多少;

    f[1]=a[1];

    (f[i]=min{f[j]+a[i]|i-j<=k})

    然后可以(O(n^2))的做;

    考虑优化:

    (f[i]=min{f[j]|i-j<=k}+a[i])

    显然可以考虑单调队列优化w

    用优先队列优化就好了√;

    #include<bits/stdc++.h>
    
    using namespace std;
    
    int n,k;
    int a[1010],dp[1010];
    
    int main(){
    	scanf("%d %d",&n,&k);
    	for(int i=1;i<=n;i++) scanf("%d",&a[i]);
    	memset(dp,0x3f,sizeof(dp));
    	dp[0]=0;
    	dp[1]=a[1];
    	for(int i=2;i<=n;i++) {
    		for(int j=i-1;i-j<=k&&j>=0;j--)
    			dp[i]=min(dp[i],dp[j]+a[i]);
    		//cout<<dp[i]<<endl;
    	}
    	printf("%d",dp[n]);
    	return 0;
    }
    
  • 相关阅读:
    无预挖无ICO-潜力币XDAG最强攻略
    DAG也许是真正的区块链3.0
    k-means+python︱scikit-learn中的KMeans聚类实现( + MiniBatchKMeans)
    使用sklearn进行K_Means聚类算法
    机器学习sklearn19.0聚类算法——Kmeans算法
    线性判别分析LDA原理总结
    LNMP V1.4一键快速部署Let's Encrypt免费SSL证书
    LNMP 1.x升级到LNMP 1.4教程及注意事项和多PHP版本使用教程
    Config Server高可用
    Config非对称加解密
  • 原文地址:https://www.cnblogs.com/zhuier-xquan/p/11519665.html
Copyright © 2011-2022 走看看