https://www.luogu.com.cn/problem/P1025

题目描述

将整数n分成k份,且每份不能为空,任意两个方案不相同(不考虑顺序)。

例如:n=7,k=3,下面三种分法被认为是相同的。

1,1,5;
1,5,1;
5,1,1.

问有多少种不同的分法。

输入格式

n,k (6<n≤200,2≤k≤6)

输出格式

1个整数,即不同的分法。

输入输出样例

输入 
 
输出

说明/提示

四种分法为:
1,1,5;
1,2,4;
1,3,3;
2,2,3.

解法一(DFS):

DFS算是比较容易想到的,但需要剪枝。

void DFS(int sum,int step,int k)

k 表示上一份分了多少个,这次就从k个开始分,sum表示到目前为止一共分了多少个,step表示到目前为止一共分了多少份。

由于方案数不能相同,所以枚举的个数要保持递增(或递减),我们可以进行重复性剪枝,记录k(上一份分了多少个),这次就从k个开始分起。

同时我们还要进行可行性剪枝,每次只要i从k枚举到i*(m - step) <= n-sum 就可以了。

因为下一份分的值不能比当前的i小,假设以后每份都分i,那么如果i*(m - step) > n-sum,则说明剩余的值不够分了,当前的i就不可行了,不需要继续DFS了。

 #include <stdio.h>
#include <string.h>
#include <iostream>
#include <string>
#include <math.h>
#include <algorithm>
#include <vector>
#include <stack>
#include <queue>
#include <set>
#include <map>
#include <sstream>
const int INF=0x3f3f3f3f;
typedef long long LL;
const int mod=1e9+;
const int maxn=1e4+;
using namespace std; int n,m;
int ans; void DFS(int sum,int step,int k)//k表示上一份分到了多少个,重复性剪枝
{
if(step==m)
{
if(sum==n) ans++;
return ;
}
for(int i=k;i*(m-step)<=n-sum;i++)//可行性剪枝
DFS(sum+i,step+,i);
} int main()
{
#ifdef DEBUG
freopen("sample.txt","r",stdin);
#endif scanf("%d %d",&n,&m);
DFS(,,);
printf("%d\n",ans); return ;
}

解法二(DP):

dp[ i ][ j ]表示将整数 i 划分为 j 份 的方案数。

首先,如果拿到一个整数 i ,因为题目中要求每份不能为空,因此必须先拿出 j 个数位将 j 份分别放上1,此时剩下 i - j个数。

那么剩下的数如何处理呢?可以将其全部分到一份当中(dp[ i-j ][1]),也可以分到两份中(dp[ i-j ][2]),...,也可以分到 j 份中(dp[ i-j ][ j ]),将每一种分法全部加起来,和即为dp[ i ][ j ]。

不过这个式子看起来并不简洁,为了求得一个简洁的式子,我们再求一个dp[i-1][j-1],

比较上面两个式子可得,

上式对应两种情况:

1.有一份只分了一个1,剩下的 i-1 要分成 j-1 份,对应dp[ i-1 ][ j-1 ]。
2.每一份的值都大于1,也就是先在j份中,每一份都放一个1,然后还剩下 i-j 个,再把这 i-j 个再分给这 j 份,对应dp[ i-j ][ j ]。(此时 i 必须大于 j )

 #include <stdio.h>
#include <string.h>
#include <iostream>
#include <string>
#include <math.h>
#include <algorithm>
#include <vector>
#include <stack>
#include <queue>
#include <set>
#include <map>
#include <sstream>
const int INF=0x3f3f3f3f;
typedef long long LL;
const int mod=1e9+;
const int maxn=1e4+;
using namespace std; int dp[][]; int main()
{
#ifdef DEBUG
freopen("sample.txt","r",stdin);
#endif int n,m;
scanf("%d %d",&n,&m);
for(int i=;i<=n;i++)
{
dp[i][]=;
for(int j=;j<=m;j++)
{
if(i==j) dp[i][j]=;
else if(i>j) dp[i][j]=dp[i-][j-]+dp[i-j][j];
}
}
printf("%d\n",dp[n][m]); return ;
}

-

数的划分(DFS、DP)的更多相关文章

  1. P1025 数的划分 dfs dp

    题目描述 将整数nn分成kk份,且每份不能为空,任意两个方案不相同(不考虑顺序). 例如:n=7n=7,k=3k=3,下面三种分法被认为是相同的. 1,1,51,1,5;1,5,11,5,1;5,1, ...

  2. 洛谷P1025 数的划分【dp】

    将整数nn分成kk份,且每份不能为空,任意两个方案不相同(不考虑顺序). 例如:n=7n=7,k=3k=3,下面三种分法被认为是相同的. 1,1,51,1,5; 1,5,11,5,1; 5,1,15, ...

  3. 【noi 2.6_8787】数的划分(DP){附【转】整数划分的解题方法}

    题意:问把整数N分成K份的分法数.(与"放苹果"不同,在这题不可以有一份为空,但可以类比)解法:f[i][j]表示把i分成j份的方案数.f[i][j]=f[i-1][j-1](新开 ...

  4. 【dfs】p1025 数的划分

    P1025 数的划分 题目描述 将整数n分成k份,且每份不能为空,任意两个方案不相同(不考虑顺序). 例如:n=7,k=3,下面三种分法被认为是相同的. 1,1,5; 1,5,1; 5,1,1; 问有 ...

  5. dp练习(8)——数的划分

    1039 数的划分 2001年NOIP全国联赛提高组  时间限制: 1 s  空间限制: 128000 KB  题目等级 : 黄金 Gold 题解       题目描述 Description 将整数 ...

  6. codevs——1039 数的划分

    1039 数的划分 2001年NOIP全国联赛提高组  时间限制: 1 s  空间限制: 128000 KB  题目等级 : 黄金 Gold 题解       题目描述 Description 将整数 ...

  7. P1025 数的划分——简单题刷傻系列

    P1025 数的划分 学傻了,学傻了,什么dp搜索什么啊: #include<cstdio> #include<cstring> #include<algorithm&g ...

  8. dfs+dp思想的结合------hdu1078

    首先是题目的意思: 从一个正方形的0,0点开始走,只能横着走,竖着走,最多走k步,下一个点的数一定要比当前这个点的值大,每走一步,就加上下一个点的数据,问数据最大能有多少. 首先遇到这种题目,走来走去 ...

  9. C语言 · 数的划分

    算法训练 数的划分   时间限制:1.0s   内存限制:256.0MB        锦囊1 使用动态规划. 锦囊2 用F[i,j,k]表示将i划分成j份,最后一份为k的方案数,则F[i,j,k]= ...

  10. 数的划分(NOIP2001&水题测试2017082401)

    题目链接:数的划分 这题直接搜索就行了.给代码,思路没什么好讲的,要讲的放在代码后面: #include<bits/stdc++.h> using namespace std; int d ...

随机推荐

  1. Thymeleaf(一)---引入js/css文件

    th:href="@{/static/css/style.css}" th:src="@{/static/js/thymeleaf.js}" index.htm ...

  2. Window Server 2019 配置篇(6)- 利用组策略实现域内自动安装软件

    上次我们建立了WSUS实现了更新管理,那么现在我们需要的是让集群内的客户机(之后会建立在hyper-v集群上)和服务器都能装上三个软件 1. Microsoft Team 2. Notepad++ 3 ...

  3. Window Server 2019 配置篇(4)- 配置WDS实现自动部署服务

    上次我们建立了hyper-v集群,那么我们这次需要对集群内的客户机和外部的服务器进行自动部署,这时候需要WDS服务 WDS服务是一种自动部署服务,能够对无OS的计算机进行操作系统的部署 首先建立虚拟机 ...

  4. 说说我当初是如何学Linux的

    今天我就说说我当初是如何从一名普通桌面维护工程师,通过学习和努力转成Linux运维工程师的,以及作为Linux运维工程师需要一些什么技能和知识,希望可以帮到一些对Linux有兴趣或者想往Linux这个 ...

  5. Exchange 2003 群集迁移 & SPS 2003 迁移、SQL Server 2000群集

    哈哈,本人自己写的文档,内容太多了,有195页,上传到Blog里面,应该是很难看的,排版也不太好. 记得下载时后改名字,用WinRAR解压合并. 第1章 迁移环境介绍 第2章 共享磁盘柜配置 第3章 ...

  6. bugku - pwn wp

    一. PWN1 题目:nc 114.116.54.89 10001 1.  直接kali里面跑nc 2.ls看看有啥 3.明显有一个flag cat查看一下 搞定 二 . PWN2 题目:给了nc 1 ...

  7. 【SQL必知必会笔记(2)】检索数据、排序检索数据

    上个笔记中介绍了一些关于数据库.SQL的基础知识,并且创建我们后续练习所需的数据库.表以及表之间的关系,从本文开始进入我们的正题:SQL语句的练习. 文章目录 1.检索数据(SELECT语句) 1.1 ...

  8. 类的始祖Object

    一.概述 Object时java中顶级父类,也是唯一没有父类的类:它是整个java中最基本的类,在java中所有的类都默认继承了Object. 二.重要方法 1.clone方法 克隆出一个新的对象. ...

  9. 六、CI框架之分配变量

    一.在controllers里面添加 $this->load->vars('m_Str1','我是一个字符串变量'); 二.在View中添加相应代码 界面显示效果如下: 不忘初心,如果您认 ...

  10. POJ 2771 最大点独立集

    这是经典的最大点独立集 还是可以转化成最大匹配数,为什么呢,因为求出最大匹配数之和,匹配的边的两个端点互斥,只能去一个,所以最后结果就用总点数-最大匹配数即可 #include <iostrea ...