输出整数划分表达式

###基本思路
我们假设有两个栈,top1指向具有n(n就是要划分的整数)个元素,且元素全为1的栈顶。top2刚开始时指向空栈,然后top1中元素不断出栈,进入top2。
用划分整数7举例,开始时top1指向具有7个元素,且元素全为1的栈顶top1=7。top2刚开始时指向空栈,top2=0。

1
现在top1中元素出栈,第一次出栈7个元素,此时top2将top1中出栈元素个数记下,也就是top2中有一个元素7。当top1再次出栈时发现top1中已经没有元素,此时调用Output函数将top2中的元素从栈底一个一个输出(就是由大到小输出,后面讲),出栈为7

2
这次top1第一次出栈6个元素,top2将top1中出栈元素个数记下,top2中有一个元素6。top1再次出栈时发现top1中只有一个元素,我们将最后一个元素出栈,top2中多了一个元素1,此时top1=0,top2=2。当top1=0时,调用Output函数将top2中的元素从栈底一个一个输出,出栈为6、1

3操作同上,出栈为5、2
4操作同上,出栈为5、1、1
5操作同上,出栈为4、3
6操作同上,出栈为4、2、1
7操作同上,出栈为4、1、1、1

8
这次不一样了,top1第一次出栈3个元素,top2将top1中出栈元素个数记下,top2中有一个元素3。top1再次出栈时发现还有4个元素,我们规定出栈的条件为top2为空(即top1中没有元素出栈)或top1出栈元素个数<=top2栈顶元素,即if(top2 == 0 || i <= a[top2-1]) ,满足这两个条件才可出栈。此时top2栈顶元素为3,top1中还剩4个元素,那么不能出栈4个元素,只可出栈3个,即本次出栈3个,然后出栈1个元素,最终输出3、3、1
.
.
.
依此类推,15次可完成所有划分

###代码

#include<iostream>

using namespace std;

int time = 0;//记录分解的个数 
 
void OutPut(int top2, int *a)
{
  int i;
  for(i=0;i<top2-1;i++)//从S2的栈底输出 
  {
	cout<<a[i]<<"+";
  }
  cout<<a[top2-1]<<endl;//输出最后一个元素时带上换行 
  time++;
} 

//划分函数表示不停的从S1中取元素到S2 
void Div(int top1, int top2,int *a)
{
	if(top1 == 0)//栈S1为空(已经拿完了),输出S2的内容 
	{
		OutPut(top2,a);
	}
	
	else//若S1没有拿完,则继续拿,规定第n+1次拿出的元素个数只能 <= 第n次拿出的元素个数 
	{
		for(int i = top1; i>=1; i--)
		/*
		  先把所有S1内的元素取出,挨个减少,使得第一个划分的整数减小 
		  一个for循环执行完就可以输出一个表达式 
		*/ 
		{
			/*
			 S2为空(表示第一次从S1中取元素) 或 将要出栈的元素个数不大于S2栈顶元素
			(即后一次拿出的元素个数只能 <= 前一次拿出的元素个数)时开始从S1中取元素
			 否则进行下一轮循环直到即将出栈的元素个数 i不大于S2栈顶元素(前一次拿出的元素个数) 
			*/
			if(top2 == 0 || i <= a[top2-1])  
			{
				a[top2] = i;//S1出栈元素的个数压入S2,记下该次出栈元素的个数
				Div(top1-i,top2+1,a);//S1少了i个元素,S2多了1个元素 
			}
		}
	 } 
} 

int main()
{
	int top1;//栈S1其实不存在,假设有top1个1在栈S1 
	int top2=0;
	while(cin>>top1)
	{
		int *a = new int [top1];
		Div(top1,top2,a);
		delete []a;
		cout<<"time:"<<time<<endl;
		time = 0;
	}
	return 0;
} 

###运行结果
第一个7是输入的,下面的是划分结果
在这里插入图片描述

评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

bugcoder-9905

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值