此题是个非常经典的题目,这个题目包含了整数划分(一)和整数划分(二)的所有情形,而且还增加了其它的情形,主要是用递归或者说是递推式来解,只要找到了递推式剩下的任务就是找边界条件了,我觉得边界也是非常重要的一步,如果找不准边界,这个题也很难做出来,当时我就是找边界找了好长时间,边界得琢磨琢磨。递推步骤如下:
第一行:将n划分成若干正整数之和的划分数。
状态转移方程:dp[i][j]:和为i、最大数不超过j的拆分数
dp[i][j]可以分为两种情况:1、拆分项至少有一个j 2、拆分项一个j也没有
dp[i][j] = dp[i-j][[j] + dp[i][j-1]
第二行:将n划分成k个正整数之和的划分数。
dp[n-k][k]:相当于把k个1从n中拿出来,然后和n-k的拆分项相加的个数
第三行:将n划分成若干最大不超过k的正整数之和的划分数。
dp[n][k]
第四行:将n划分成若干奇正整数之和的划分数。
dp1[i][j]是当前的划分数为i,最大值为j时的中的划分数,则状态转移方程为
if(i < j && j % 2 == 1)
dp1[i][j] = dp1[i][i]
if(i < j && j % 2 == 0) (最大数不可能为偶数)
dp1[i][j] = dp1[i][i-1]
划分数中有j时的划分为dp[i][j - 2],因为它是奇数,所以要减2,
如果划分数中没有j的时候, 则它的数目可以写成dp1[i-j][j];意思就是i去掉j后,然后再划分最大为j的
即dp1[i][j] = dp1[i-j][j] + dp1[i][j-2]
第五行:将n划分成若干完全不同正整数之和的划分数。
dp2[i][j]可以分两种情况:1、dp1[i][j-1]为不选择j时的方案 2、dp1[i-j][j-1]为选择j时的方案
0-1背包:dp2[i][j] = dp2[i][j-1] + dp2[i-j][j-1]
方法一(递归法):
#include <stdio.h>
//less_m(n, m)表示将n划分为最大是m的数
int less_m(int n, int m)
{
if(n == || m == )
return ;
if(n < m)
return less_m(n, n);
else if(n == m)
return + less_m(n, m - );
else
return less_m(n, m - ) + less_m(n - m, m);
}
//count(n, m)表示将n划分为m个数
int count(int n, int m)
{
if(n < m)
return ;
if(m == || n == m)
return ;
else
return count(n - , m - ) + count(n - m, m);
}
//odd(n, m)表示将n划分为最大数为m的奇数之和
int odd(int n, int m)
{
if(m == )
return ;
if(n == && m % == )
return ;
if(n == && m == )
return ;
if(n < m)
{
if(n % == )
return odd(n, n - );
else
return odd(n, n);
}
else
{
return odd(n - m, m) + odd(n, m - );
} }
//not_duplicate(n, m)是将n划分为最大为m的数, 并且没有重复的
int not_duplicate(int n, int m)
{
if(m == )
return ;
if(n == || n == )
return ;
if(n < m)
return not_duplicate(n, n);
else
return not_duplicate(n, m - ) + not_duplicate(n - m, m - );
} int main()
{
int n, k;
while(~scanf("%d %d", &n, &k))
{
printf("%d\n", less_m(n, n));
printf("%d\n", count(n, k));
printf("%d\n", less_m(n, k));
if(n % == )
printf("%d\n", odd(n, n));
else
printf("%d\n", odd(n, n - ));
printf("%d\n\n", not_duplicate(n, n));
} return ;
}
方法二(递推法dp):
#include <stdio.h>
const int MAX = ;
int dp[MAX][MAX], dp1[MAX][MAX], dp2[MAX][MAX];
void divide()
{
dp[][] = ;
for(int i = ; i < MAX; i++)
{
for(int j = ; j < MAX; j++)
{
if(i < j)
dp[i][j] = dp[i][i];
else
dp[i][j] = dp[i][j - ] + dp[i - j][j];
}
}
}
//这是划分奇数的函数
void divide1()
{
for(int i = ; i < MAX; i++)
dp1[i][] = ;
for(int i = ; i < MAX; i += )
dp1[][i] = ;
dp1[][] = ;
for(int i = ; i < MAX; i++)
{
for(int j = ; j < MAX; j += )
{
if(i < j)
{
if(i % == )
dp1[i][j] = dp1[i][i];
else
dp1[i][j] = dp1[i][i - ];
}
else
dp1[i][j] = dp1[i][j - ] + dp1[i - j][j];
}
}
}
//划分没有重复数字的函数
void divide2()
{
for(int i = ; i < MAX; i++)
dp2[][i] = dp2[][i] = ;
for(int i = ; i < MAX; i++)
{
for(int j = ; j < MAX; j++)
{
if(i < j)
dp2[i][j] = dp2[i][i];
else
dp2[i][j] = dp2[i][j - ] + dp2[i - j][j - ];
}
}
} int main()
{
int n, k;
divide();
divide1();
divide2();
while(~scanf("%d %d", &n, &k))
{
printf("%d\n", dp[n][n]);
printf("%d\n", dp[n - k][k]);
printf("%d\n", dp[n][k]);
//先要判断要划分的数是否是奇数
printf("%d\n", (n & ) ? dp1[n][n] : dp1[n][n - ]);
printf("%d\n\n", dp2[n][n]);
} }
NYOJ-571 整数划分(三)的更多相关文章
-
nyoj 90 整数划分
点击打开链接 整数划分 时间限制:3000 ms | 内存限制:65535 KB 难度:3 描述 将正整数n表示成一系列正整数之和:n=n1+n2+-+nk, 其中n1≥n2≥-≥nk≥1,k≥ ...
-
2014北大研究生推免机试(校内)-复杂的整数划分(DP进阶)
这是一道典型的整数划分题目,适合正在研究动态规划的同学练练手,但是和上一个随笔一样,我是在Coursera中评测通过的,没有找到适合的OJ有这一道题(找到的ACMer拜托告诉一声~),这道题考察得较全 ...
-
整数划分 Integer Partition(二)
本文是整数划分的第二节,主要介绍整数划分的一些性质. 一 先来弥补一下上一篇文章的遗留问题:要求我们所取的 (n=m1+m2+...+mi )中 m1 m2 ... mi连续,比如5=1+4就不符合 ...
-
整数划分 Integer Partition(一)
话说今天百度面试,可能是由于我表现的不太好,面试官显得有点不耐烦,说话的语气也很具有嘲讽的意思,搞得我有点不爽.Whatever,面试中有问到整数划分问题,回答这个问题过程中被面试官搞的不胜其烦,最后 ...
-
大概是:整数划分||DP||母函数||递推
整数划分问题 整数划分是一个经典的问题. Input 每组输入是两个整数n和k.(1 <= n <= 50, 1 <= k <= n) Output 对于每组输入,请输出六行. ...
-
51nod p1201 整数划分
1201 整数划分 基准时间限制:1 秒 空间限制:131072 KB 分值: 80 难度:5级算法题 将N分为若干个不同整数的和,有多少种不同的划分方式,例如:n = 6,{6} {1,5} {2, ...
-
NYOJ 746---整数划分(四)(区间DP)
题目链接 描述 暑假来了,hrdv 又要留学校在参加ACM集训了,集训的生活非常Happy(ps:你懂得),可是他最近遇到了一个难题,让他百思不得其解,他非常郁闷..亲爱的你能帮帮他吗? 问题是我们经 ...
-
整数划分 (区间DP)
整数划分(四) 时间限制:1000 ms | 内存限制:65535 KB 难度:3 描述 暑假来了,hrdv 又要留学校在参加ACM集训了,集训的生活非常Happy(ps:你懂得),可是他最近 ...
-
51nod1201 整数划分
01背包显然超时.然后就是一道神dp了.dp[i][j]表示j个数组成i的方案数.O(nsqrt(n)) #include<cstdio> #include<cstring> ...
随机推荐
-
大理石在哪里UVa 10474
我自己写的代码 #include<iostream>#include<algorithm>using namespace std;int main(){ int N,a[ ...
-
AJAX应用优势
国内翻译(仅音译)常为 “阿贾克斯” 和阿贾克斯足球队同音. 使用ajax 构建应用程序 这个术语源自描述从基于 Web 的应用到基于数据的应用的转换.在基于数据的应用中,用户需求的数据如联系人列表, ...
-
V-rep学习笔记:曲柄摇杆机构
在ADAMS中创建一个曲柄摇杆机构很方便,但是V-rep中建模就比较麻烦.下面将自己在V-rep中建立曲柄摇杆机构模型的过程记录下来(由于对V-rep不是很熟,可能会有一些错误,只能等以后发现了再改进 ...
-
Tutorial: Facebook analytics using Power BI Desktop
In this tutorial you learn how to import and visualize data from Facebook. During the tutorial you'l ...
-
一个ajax的后台controller
@RequestMapping("/api/merBrand") @ResponseBody public ResultBrand merBrand(HttpServletRequ ...
-
reshape2 数据操作 数据融合( cast)
我们在做数据分析的时候,对数据进行操作也是一项极其重要的内容,这里我们同样介绍强大包reshape2,其中的几个函数,对数据进行操作cast和melt两个函数绝对少不了. 首先是cast,把长型数据转 ...
-
关于ES6 的对象解构赋值
之 前写了关于ES6数组的解构 现在 go on ; 解构不仅可以用于数组,还可以用于对象: 对象的解构和数组有一个重要的不同.数组的元素是按次序排列的,变量的取值是由他的位置决定的:而对象的属性没有 ...
-
jQuery动画切换引擎插件Velocity.js
Velocity.js 官网 Velocity.js实现弹出式相框 慕课网 极棒的jquery动画切换引擎插件Velocity.js jQ库 (function($){ // 普通调用 /*$('#d ...
-
AS 自定义 Gradle plugin 插件 案例 MD
Markdown版本笔记 我的GitHub首页 我的博客 我的微信 我的邮箱 MyAndroidBlogs baiqiantao baiqiantao bqt20094 baiqiantao@sina ...
-
数据库操作API 或万能的双下划线
数据库操作API: 类型 描述 exact 精确匹配: polls.get_object(id__exact=14). iexact 忽略大小写的精确匹配: polls.objects.filter( ...