Game of Connections -组合数学中的计数问题

本文介绍了一款简单的圆形配对游戏,并利用卡特兰数解决游戏中不同配对方式的数量问题。通过分析游戏规则,文章提出了有效的算法实现,并给出了具体的代码示例。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

问题描述:

This is a small but ancient game. You are supposed to write down the numbers 1, 2, 3, ... , 2n - 1, 2n consecutively in clockwise order on the ground to form a circle, and then, to draw some straight line segments to connect them into number pairs. Every number must be connected to exactly one another. And, no two segments are allowed to intersect. 


It's still a simple game, isn't it? But after you've written down the 2n numbers, can you tell me in how many different ways can you connect the numbers into pairs? Life is harder, right? 

输入:

Each line of the input file will be a single positive number n, except the last line, which is a number -1. You may assume that 1 <= n <= 100. 

输出:

For each n, print in a single line the number of ways to connect the 2n numbers into pairs. 

输入样例:

2

3

-1

输出样例:

2

5


问题分析:刚开始不知道是卡特兰数,然后画图推了一下:从点1开始顺时针排一个圆,先把顶点为4个的方案画出来,然后画6个的,就会发现如果将点1与2相连或者点1与6相连的时候,剩下四个点的方案就是顶点为4时候的,此时得出的方案数:2*2=4,如果点1与4相连,则2,3与5,6则又是一种方案(顶点为2个的时候)4+1*1,由此推出,将点1与偶数点相连再把点1与偶数点相连分隔出的两边的方案数相乘,则得到答案,附上代码(刚开始WA了两遍还以为自己思路错了,然后去poj上看了一下讨论,copy了一个大整数类,然后就过了哈哈):

#include 
using namespace std;
typedef unsigned long long LL;
const int maxn = 200;
struct bign {
	int len, s[maxn];

	bign() {
		memset(s, 0, sizeof(s));
		len = 1;
	}

	bign(int num) {
		*this = num;
	}

	bign(const char* num) {
		*this = num;
	}

	bign operator =(int num) { //直接以整数赋值
		char s[maxn];
		sprintf(s, "%d", num);
		*this = s;
		return *this;
	}

	bign operator =(const char* num) { //以字符串赋值
		len = strlen(num);
		for(int i = 0; i < len; i++)
			s[i] = num[len - i - 1] - '0';
		return *this;
	}

	string str() const { //将bign转化成字符串
		string res = "";
		for(int i = 0; i < len; i++)
			res = (char) (s[i] + '0') + res;
		if(res == "")
			res = "0";
		return res;
	}

	bign operator +(const bign& b) const { //重载+号运算
		bign c;
		c.len = 0;
		for(int i = 0, g = 0; g || i < max(len, b.len); i++) {
			int x = g;
			if(i < len) x += s[i];
			if(i < b.len) x += b.s[i];
			c.s[c.len++] = x % 10;
			g = x / 10;
		}
		return c;
	}

	void clean() { //去掉前到0
		while(len > 1 && !s[len - 1])
			len--;
	}

	bign operator *(const bign& b) { //重载*号运算
		bign c;
		c.len = len + b.len;
		for(int i = 0; i < len; i++)
			for(int j = 0; j < b.len; j++)
				c.s[i + j] += s[i] * b.s[j];
		for(int i = 0; i < c.len - 1; i++) {
			c.s[i + 1] += c.s[i] / 10;
			c.s[i] %= 10;
		}
		c.clean();
		return c;
	}

	bign operator -(const bign& b) { //重载-号运算
		bign c;
		c.len = 0;
		for(int i = 0, g = 0; i < len; i++) {
			int x = s[i] - g;
			if(i < b.len)
				x -= b.s[i];
			if(x >= 0)
				g = 0;
			else {
				g = 1;
				x += 10;
			}
			c.s[c.len++] = x;
		}
		c.clean();
		return c;
	}

	bool operator <(const bign& b) const { //重载<号运算
		if(len != b.len)
			return len < b.len;
		for(int i = len - 1; i >= 0; i--)
			if(s[i] != b.s[i])
				return s[i] < b.s[i];
		return false;
	}

	bool operator >(const bign& b) const { //重载>号运算
		return b < *this;
	}

	bool operator <=(const bign& b) { //重载<=号运算
		return !(b > *this);
	}

	bool operator ==(const bign& b) { //重载>=号运算
		return !(b < *this) && !(*this < b);
	}

	bign operator +=(const bign& b) { //重载+=号运算
		*this = *this + b;
		return *this;
	}
};

istream& operator >>(istream &in, bign& x) { //重载输入运算符
	string s;
	in >> s;
	x = s.c_str();
	return in;
}

ostream& operator <<(ostream &out, const bign& x) { //重载输出运算符
	out << x.str();
	return out;
}

bign a[103];
int main()
{
    memset(a,0,sizeof(a));
    a[1]=1;
    a[2]=2;
    int n;
    int temp=3;
    for(int i=3; i<=100; i++)
    {
        a[i]=0;
        for(int j=2; j<=i; j++)
        {
            a[i]+=a[j-1]*a[i-j];
        }
        a[i]=a[i]+a[i-1]+a[i-1];
    }
    while(cin>>n&&n>0)
    {
        cout<

评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值