数的划分(DFS、DP)
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)的更多相关文章
- P1025 数的划分 dfs dp
题目描述 将整数nn分成kk份,且每份不能为空,任意两个方案不相同(不考虑顺序). 例如:n=7n=7,k=3k=3,下面三种分法被认为是相同的. 1,1,51,1,5;1,5,11,5,1;5,1, ...
- 洛谷P1025 数的划分【dp】
将整数nn分成kk份,且每份不能为空,任意两个方案不相同(不考虑顺序). 例如:n=7n=7,k=3k=3,下面三种分法被认为是相同的. 1,1,51,1,5; 1,5,11,5,1; 5,1,15, ...
- 【noi 2.6_8787】数的划分(DP){附【转】整数划分的解题方法}
题意:问把整数N分成K份的分法数.(与"放苹果"不同,在这题不可以有一份为空,但可以类比)解法:f[i][j]表示把i分成j份的方案数.f[i][j]=f[i-1][j-1](新开 ...
- 【dfs】p1025 数的划分
P1025 数的划分 题目描述 将整数n分成k份,且每份不能为空,任意两个方案不相同(不考虑顺序). 例如:n=7,k=3,下面三种分法被认为是相同的. 1,1,5; 1,5,1; 5,1,1; 问有 ...
- dp练习(8)——数的划分
1039 数的划分 2001年NOIP全国联赛提高组 时间限制: 1 s 空间限制: 128000 KB 题目等级 : 黄金 Gold 题解 题目描述 Description 将整数 ...
- codevs——1039 数的划分
1039 数的划分 2001年NOIP全国联赛提高组 时间限制: 1 s 空间限制: 128000 KB 题目等级 : 黄金 Gold 题解 题目描述 Description 将整数 ...
- P1025 数的划分——简单题刷傻系列
P1025 数的划分 学傻了,学傻了,什么dp搜索什么啊: #include<cstdio> #include<cstring> #include<algorithm&g ...
- dfs+dp思想的结合------hdu1078
首先是题目的意思: 从一个正方形的0,0点开始走,只能横着走,竖着走,最多走k步,下一个点的数一定要比当前这个点的值大,每走一步,就加上下一个点的数据,问数据最大能有多少. 首先遇到这种题目,走来走去 ...
- C语言 · 数的划分
算法训练 数的划分 时间限制:1.0s 内存限制:256.0MB 锦囊1 使用动态规划. 锦囊2 用F[i,j,k]表示将i划分成j份,最后一份为k的方案数,则F[i,j,k]= ...
- 数的划分(NOIP2001&水题测试2017082401)
题目链接:数的划分 这题直接搜索就行了.给代码,思路没什么好讲的,要讲的放在代码后面: #include<bits/stdc++.h> using namespace std; int d ...
随机推荐
- python基础数据类型--元组(tuple)
python基础数据类型--元组(tuple) 一.元组的定义和特性 定义:与列表相似,只不过就是将[ ] 改成 ( ) 特性:1.可以存放多个值 2.不可变 3.按照从左到右的顺序定义元组元素,下标 ...
- js数字排序方法
function bubbleSort(arr){ var flag = false; // 定义一个变量为false,未交换位置 for(var i=0;i<arr.length-1;i++) ...
- Golang的标识符命名规则
Golang的标识符命名规则 作者:尹正杰 版权声明:原创作品,谢绝转载!否则将追究法律责任. 一.关键字 1>.Go语言有25个关键字 Go语言的25个关键字如下所示: break,defau ...
- S7-200 smart 网线下载与调试配置
打开 step microwin 7 smart 软件. 连接PLC 打开 通讯模块 我把电脑的改成了如下 我编写的简单的程序 通过外部一个开关 实现输出的一个 IO 的接通与断开 下载完成程序以后 ...
- NRF52840与NRF52832的性能区别
蓝牙版本的不断更新,大部分客户慢慢都向往着蓝牙5.0.当然对于前不久NORDIC刚出的蓝牙5.0 NRF52840,很多人都还不是很了解.NRF52840可以说是NRF52832的超强升级版,虽然同样 ...
- ROS大型工程学习(二) 怎么阅读大型工程
基本思路是由点到面,由浅到深. 1.首先从launch文件入手. 文件中会看到比如: <node ns="> <rosparam command="load&qu ...
- ROS常见问题(三) 报错are you sure it is properly registered and that the containing library is built?
报错: [FATAL] [1576042404.913706482]: Failed to create the global_planner/GlobalPlanner planner, are y ...
- 一次C语言编程遇到的问题总结
今天用C语言做了一个简单的用户登录注册存取款等功能的系统,发现有很多功能并不会实现,大概是使用Java太多了导致许多C的知识都忘记了,现在把碰到的问题总结如下: 1.字符串复制问题 java等一些编程 ...
- 【Cantor表】蒟蒻题解
原题:传送门 (上图摘自网站OpenJudge - NOI题库2.1 Cantor表) 本蒟蒻的题解,让大神们见笑了! 首先,进行找规律. 大家可以发现: 1.当分子是一的时候,且分子和分母的和是偶数 ...
- JavaWeb学习——了解HTML
JavaWeb学习——了解HTML 摘要:本文主要简单介绍了什么是HTML以及如何使用. 定义 是什么 HTML(Hyper Text Markup Language),指的是超文本标记语言. 超文本 ...