zoukankan      html  css  js  c++  java
  • 切割多边形

    Description

    在一个凸n边形中,通过不相交于n边形内部的对角线,把n边形拆分成若干三角形。现在的任务是从键盘输入凸多边形的边数n,求不同剖分的方案数Cn。

    Analysis

    困难的一题。

    不谈1000的数据量加上大整数会不会TLE,先分析一下转移方程。

    不妨以点为突破口。显而易见,每个点要么被连接,要么不被连接。

    • 当不被连接时,其相邻两点一定连接,则n边形转化为n-1边形。
    • 当被连接时,可以与n-3个点相连,那么相连之后分割出i边形和n-i+2边形。为了防止重复,即连接第i个点时要保证不连接i+1n-3,可以将n-i+2边形转化为n-i+1边形,即自动视为此点不与i+1n-3个点相连。

    动规方程:

    dp[i]=dp[i-1]+dp[3]*dp[i-2]+...+dp[i-1]*dp[2]
    

    因为dp[2]=1,所以又可以写成

    dp[i]=dp[2]*dp[i-1]+...+dp[i-1]*dp[2]
    

    状态转移复杂度为O(n^2),再算上高精度处理O(1000),TLE。

    那么,怎么通过O(n)乃至更小的复杂度转移状态呢。我不知道,所以看了hj解题报告,了解了Catlan Queue。

    不进行证明。

    Code

    #include <bits/stdc++.h>
    
    struct bigint{
    	int len,num[5010];
    	bigint operator = (int eq){
    		len=0;
    		memset(num,0,sizeof(num));
    		while(eq){
    			num[len++]=eq%10;
    			eq/=10;
    		}
    		return *this;
    	}
    	bigint operator * (bigint mt){
    		bigint ans;
    		ans.len=len+mt.len-1;
    		memset(ans.num,0,sizeof(ans.num));
    		for(int i=0;i<len;i++)
    			for(int j=0;j<mt.len;j++)
    				ans.num[i+j]+=num[i]*mt.num[j];
    		int add=0;
    		for(int i=0;i<ans.len;i++){
    			ans.num[i]+=add;
    			add=ans.num[i]/10;
    			ans.num[i]%=10;
    		}
    		while(add){
    			ans.num[ans.len++]=add%10;
    			add/=10;
    		}
    		return ans;
    	}
    	bigint operator * (int mt){
    		bigint bigmt;
    		bigmt=mt;
    		return *this*bigmt;
    	}
    	bigint operator *= (int mt){
    		return *this=*this*mt;
    	}
    	bigint operator / (int dv){
    		bigint ans;
    		ans.len=len;
    		memset(ans.num,0,sizeof(ans.num));
    		int bc=0;
    		for(int i=len-1;i>=0;i--){
    			bc=bc*10+num[i];
    			if(bc>=dv)ans.num[i]=bc/dv,bc%=dv;
    		}
    		while(ans.len-1&&!ans.num[ans.len-1])ans.len--;
    		return ans;
    	}
    	bigint operator /= (int dv){
    		return *this=*this/dv;
    	}
    	friend std::ostream& operator << (std::ostream& out,bigint ans){
    		for(int i=ans.len-1;i+1;i--)
    			out<<ans.num[i];
    		return out;
    	}
    };
    
    int n;
    
    bigint Catlan(int x){
    	bigint ans;
    	ans=x+2;
    	for(int i=x+3;i<=x*2;i++)
    		ans*=i;
    	for(int i=2;i<=x;i++)
    		ans/=i;
    	return ans;
    }
    
    int main(){
    	freopen("test.in","r",stdin);
    	freopen("test.out","w",stdout);
    	std::cin>>n;
    	if(n==1)std::cout<<0<<std::endl;
    	else if(n<4)std::cout<<1<<std::endl;
    	else std::cout<<Catlan(n-2)<<std::endl;
    	return 0;
    }
    
  • 相关阅读:
    基于Metaweblog API 接口一键发布到国内外主流博客平台
    uva144 Student Grants
    Uva 10452
    Uva 439 Knight Moves
    Uva 352 The Seasonal War
    switch语句
    java——基础知识
    我的lua学习2
    codeforces 431 D. Random Task 组合数学
    codeforces 285 D. Permutation Sum 状压 dfs打表
  • 原文地址:https://www.cnblogs.com/qswx/p/9492564.html
Copyright © 2011-2022 走看看