深搜和DP方法解决数的划分问题

数的划分

题目描述
    积极探索太空的回报是丰厚的,因为魔法世界的科学家后来通过挖掘史前文明遗址发现,他们所在的星球,每隔一亿五千万年
左右就会发生一次由天外陨石或其他意外事件引发的物种大灭绝。称霸星球一亿多年的恐龙,就是因此而灭绝的。只有积极进
取,锐意创新的宇宙文明,才有可能躲过这场“天罚”。现在,天顶星人对魔法世界发动了大规模陨石攻击,魔法世界的太空防御
系统及时作出反应,将防御能量n分成k份以对付k个陨石,已知每份不能为空(否则会被陨石击中),任意两份不能相同(不考
虑顺序)。例如:n=7,k=3,下面三种分法被认为是相同的:1,1,5; 1,5,1; 5,1,1。问有多少种不同的分法。
输入
n,k (6<n≤200,2≤k≤6)
输出
一个整数,即不同的分法。
样例输入
7 3
样例输出
4
深搜思路分析:

首先观看题目规模2<=k<=6,规模不是很大,考虑到用深搜来做,依次枚举n以内的数字在k个格子内填充,为了避免重复,确定顺序从小到大进行填充。
AC 代码:

#include<bits/stdc++.h>
using namespace std;
int n,k,ans=0;
void dfs(int step,int d,int num) //step表示枚举的数,d表示需要填充的格子数,num即为要划分的那个数
{
    if(d==1)
    {
        ans++;
        return;
    }
    for(int i=step;i<=num/d;i++)
    {
        dfs(i,d-1,num-i);
    }
}
int main()
{
    cin>>n>>k;
    dfs(1,k,n);
    cout<<ans<<endl;
    return 0;
}

DP思路分析:

这道题可以看成是将n个小球装入到k个盒子里面,每个盒子里面至少有一个小球,可以分成两种状态:
1、至少有一个盒子内只有一个球;
2、每个盒子里的球的数量都大于1个;
两种状态之和即为所有状态的情况。
设dp[i][j]表示将 i 个球装入到 j 个盒子内,则状态1可表示为dp[ i - 1 ][ j - 1 ];状态2可表示为dp[ i - j ][ j ];
则可得到状态转移方程为dp[ i ][ j ]=dp[ i - 1][ j - 1]+dp[ i - j ][ j ];
话不多说,差不多就是这样,上代码:
AC 代码:

#include<bits/stdc++.h>
using namespace std;
int dp[300][300];
int main()
{
    int a[210],n,k,ans,sum1,i,j;
    scanf("%d%d",&n,&k);
    for(i=1;i<=n;i++)//处理一下边界 
    {
    	dp[i][1]=1;
    	dp[i][0]=1;
	}
	for(i=2;i<=k;i++)
	{
		dp[0][i]=0;
		dp[1][i]=0;
	}
	for(i=2;i<=n;i++)
	{
		for(j=2;j<=k;j++)
		{
			if(j>i) dp[i][j]=0;
			else dp[i][j]=dp[i-1][j-1]+dp[i-j][j];
		}
	}
	printf("%d",dp[n][k]);
    return 0;
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值