{2018.4.28}荀(gou)彧(huo)同学的递归小结

终于做到递归了啊;

很有意思的东西;

还是要做个小结;

边讲题边总结吧;

1>整数划分;

上题目:

题目描述

将正整数n表示成一系列正整数之和:n=n1+n2+?+nk,其中8>=n1≥n2≥?≥nk≥1,k≥1。正整数n的这种表示称为正整数n的划分。

例如正整数6有如下11种不同的划分:

    6;
    5+1;
    4+2,  4+1+1;
    3+3,  3+2+1,  3+1+1+1;
    2+2+2,2+2+1+1,2+1+1+1+1;
    1+1+1+1+1+1。

输入格式

一个正整数 n
保证 n<=8

输出格式

一个正整数 m,表示n可以被分成m种

input

6

output

11

看着令人非常头大的东西;

讲讲思路:

在这道题里面,yu果要直接计算p(n)的划分方案数,是一个非常非常麻烦的东西,所以啊,要手动加入一个控制变量;

将最大加数不大于m的划分方案记作p(n,m)。

两个变量中间有n<m,n>=m两种情况;

(1)yu果m>n,很明显,n的拆分不可能包含大于n的加数m,此时最大加数只能是n,因此f(n,m)==f(n,n);

(2)则n可以拆分成最大加数是m的加法式。我们把加法式分成两类,分别计数;

    (i)加式中一定包含m,形如n=m+……;

         既然加式中一定包含m,那么就可以从n中减去m,然后对n-m继续拆分,是f(n-m,m)。这种情况能得到的方案数既是f(n-m,m);

    (ii)加式中不一定包含m,则最大加数最多是m-1,这种情况的方案数是f(n,m-1);

边界条件:

    f(n,1)=1    表示当最大加数是1时,整数n只有一个划分,即n个1相加;

    f(1,m)=1    表示整数n=1只有一个划分,不管最大加数m有多大;

    f(0,m)=1    表示n=0时,整数n只有一种划分;

上代码:

#include<bits/stdc++.h>
using namespace std;
int m,n,ans;
int work(int n,int m)
{
	if(n==0||m==0) return 0;
	if(n==1||m==1) return 1;
	if(n<m) return work(n,n);
	if(n==m) return work(n,n-1)+1;
	return work(n,m-1)+work(n-m,m);
}
int main()
{
	cin>>n;
	work(n,n);
	cout<<work(n,n);
	return 0;
}

其实这个代码可以变得更好看一些:

#include<bits/stdc++.h>
using namespace std;
int m,n,ans;
int work(int m,int n)
{
	if (m>n)
	{
	    return work(n,n);	
	}
	if(m==0&&n==0) return 1;
	if(m==0) return 0;
	return work(m,n-m)+work(m-1,n);
}
int main()
{
	cin>>n;
	work(n,n);
	ans=work(n,n);
	cout<<ans;
	return 0;
}

很简单很基础的一道递归题;

重点是要理解递归的概念和学会最基本的应用;

end...

2>拍卖

上题目:

题目描述

一般情况下,拍卖行的拍卖师在拍卖商品的时候都是从低价开始起拍,由买方报价,最后谁出的价格高,商品就归谁所有。但焦作有个拍卖行,拍卖师在拍卖商品时正好相反:总是从高价开始起拍,如果没有人举成交牌就降价,而且拍卖师在降价时还有规律:假如第i次报价为w元,那么第i+1次报价为w-a或者w-b元,如果降到p元时,你认为价格合适,赶快第一个举成交牌,你就花p元买下了商品。

任务:拍卖师把商品从w元降到p元的方法总数。

输入格式

文件第一行有两个正整w 和p ,第二行有有两个正整a 和b. 1 ≤ w,p ≤ 10^6  , 2 ≤ a,b ≤ 10000, a不等于b.

输出格式

文件只有一行,即所求得的方法总数。注意:测试数据中方法总数不超过MAXlongint.

样例数据

input

10  3
2  3

output

 

3

又是一道很那啥的题;

讲讲思路:

根据递归构建的三个条件(1.参数 2.边界 3.范围)来分析递归过程如何写;

(1)参数:我们只需要在意操作当前数就可以了,一个参数k表示当前数的值;

(2)边界:如果可以等于y,那么方法数要加1;

                   如果当前的数已经小于等于y,那么再往下递归也没有什么意义;

(3)范围:当前的数在选择的时候,可以选择减a,也可以选择减b,范围是两个数即可;

上代码:

#include<bits/stdc++.h>
using namespace std;
int x,y,a,b,ans=0;
int dfs(int k)
{
	if(k==y) return 1;
	if(k<y) return 0;
	return(dfs(k-a)+dfs(k-b));
}
int main()
{
	cin>>x>>y>>a>>b;
	dfs(x);
	cout<<dfs(x);
	return 0;
}

上面这个代码就是照着思路敲的,但是!

放到oj上提交却超时了;

还记得讲过的时空复杂度么?

在这里就要用空间换时间了;

满分代码:

include<bits/stdc++.h>
using namespace std;
int x,y,a,b,ans;
int f[1001000];
int dfs(int k)
{
	if(f[k]>=0)   return f[k];
	if(k==y) return 1;
	if(k<y) return 0;
	f[k]=dfs(k-a)+dfs(k-b);
	return f[k];
}
int main()
{
	cin>>x>>y>>a>>b;
	dfs(x);
	ans=0;
	memset(f,-1,sizeof(f));
	f[y]=1;
	cout<<dfs(x);
	return 0;
}

这就是所谓的记忆化搜索;

听老师说空间换时间原则是动态规划的出发点;

所提要加强运用;

end...

递归在我这种小菜鸡眼中可以说是很难了;

简短的两道题却包括了递归的基本思想;

希望对自己有些帮助吧;

全文终。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
未来社区的建设背景和需求分析指出,随着智能经济、大数据、人工智能、物联网、区块链、云计算等技术的发展,社区服务正朝着数字化、智能化转型。社区服务渠道由分散向统一融合转变,服务内容由通用庞杂向个性化、服务导向转变。未来社区将构建数字化生态,实现数据在线、组织在线、服务在线、产品智能和决策智能,赋能企业创新,同时注重人才培养和科研平台建设。 规划设计方面,未来社区将基于居民需求,打造以服务为中心的社区管理模式。通过统一的服务平台和应用,实现服务内容的整合和优化,提供灵活多样的服务方式,如推送式、订阅式、热点式等。社区将构建数据与应用的良性循环,提高服务效率,同时注重生态优美、绿色低碳、社会和谐,以实现幸福民生和产业发展。 建设运营上,未来社区强调科学规划、以人为本,创新引领、重点突破,统筹推进、整体提升。通过实施院落+社团自治工程,转变政府职能,深化社区自治法制化、信息化,解决社区治理中的重点问题。目标是培养有活力的社会组织,提高社区居民参与度和满意度,实现社区治理服务的制度机制创新。 未来社区的数字化解决方案包括信息发布系统、服务系统和管理系统。信息发布系统涵盖公共服务类和社会化服务类信息,提供政策宣传、家政服务、健康医疗咨询等功能。服务系统功能需求包括办事指南、公共服务、社区工作参与互动等,旨在提高社区服务能力。管理系统功能需求则涉及院落管理、社团管理、社工队伍管理等,以实现社区治理的现代化。 最后,未来社区建设注重整合政府、社会组织、企业等多方资源,以提高社区服务的效率和质量。通过建立社区管理服务综合信息平台,提供社区公共服务、社区社会组织管理服务和社区便民服务,实现管理精简、高效、透明,服务快速、便捷。同时,通过培育和发展社区协会、社团等组织,激发社会化组织活力,为居民提供综合性的咨询和服务,促进社区的和谐发展。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值