热门标签 | HotTags
当前位置:  开发笔记 > 编程语言 > 正文

HOJ1402:整数分解与组合优化问题研究

HOJ1402题目涉及整数划分的经典问题,旨在通过具体的实例提升对组合数学的理解和应用能力。该问题不仅考察了基本的数学原理,还要求对算法优化有深入的认识,以高效解决大规模数据下的整数分解与组合优化挑战。

HOJ1402 整数划分

http://acm.hit.edu.cn/hoj/problem/view?id=1402

【题目描述】

整数划分是一个经典的问题。希望这道题会对你的组合数学的解题能力有所帮助。

Input

每组输入是两个整数n和k。(1 <&#61; n <&#61; 50, 1 <&#61; k <&#61; n)

Output

对于每组输入&#xff0c;请输出六行。

第一行&#xff1a; 将n划分成若干正整数之和的划分数。
第二行&#xff1a; 将n划分成k个正整数之和的划分数。
第三行&#xff1a; 将n划分成最大数不超过k的划分数。
第四行&#xff1a; 将n划分成若干奇正整数之和的划分数。
第五行&#xff1a; 将n划分成若干不同整数之和的划分数。
第六行&#xff1a; 打印一个空行。

Sample Input

5 2

Sample Output

7
2
3
3
3

Hint:

  1. 将5划分成若干正整数之和的划分为&#xff1a; 5, 4&#43;1, 3&#43;2, 3&#43;1&#43;1, 2&#43;2&#43;1, 2&#43;1&#43;1&#43;1, 1&#43;1&#43;1&#43;1&#43;1
  2. 将5划分成2个正整数之和的划分为&#xff1a; 3&#43;2, 4&#43;1
  3. 将5划分成最大数不超过2的划分为&#xff1a; 1&#43;1&#43;1&#43;1&#43;1, 1&#43;1&#43;1&#43;2, 1&#43;2&#43;2
  4. 将5划分成若干奇正整数之和的划分为&#xff1a; 5, 1&#43;1&#43;3, 1&#43;1&#43;1&#43;1&#43;1
  5. 将5划分成若干不同整数之和的划分为&#xff1a; 5, 1&#43;4, 2&#43;3

 

【算法分析】

  

本题相当于5个小问题&#xff0c;首先来看最容易做的第5个小问题&#xff1a;将n划分成若干不同整数之和的划分数。则是一个典型的背包装物品问题&#xff0c;把问题转化一下&#xff0c;即一个容量为n的背包&#xff0c;重量分别为1n的物品各一个&#xff0c;求用若干物品将背包填满的方案总数。

利用动态规划的思想&#xff0c;很容易得到方程F[I,J] &#61; F[I-1,J] &#43;F[I-1,J-I]&#xff0c;其中F[I,J]表示从前I个物品中用若干个组成的总重量为J的方案总数&#xff0c;转移时要保证F[I-1,J-I]有意义。答案为F[n,n]&#xff0c;时间复杂度为O(n2)

对于前3个小问题可以归结为一个问题&#xff0c;即第2个小问题&#xff1a;把将n划分成k个正整数之和的划分数。

为了避免重复&#xff0c;我们需要按照不下降的顺序进行排列。我们形象地可以把nk份自然数划分看作n块积木堆成k列&#xff0c;那么不妨设这n块积木从左到右被堆成“阶梯状”。比如&#xff0c;下图表示的是3104份自然数划分。

 

而将该图旋转90度&#xff0c;可以很容易想出一种状态表示方法。

 

F[I,J,K]表示把J划分成I份最大为K的划分方案数&#xff0c;则有F[I,J,K] &#61; F[I-1,J-K,L]&#xff0c;其中L &#61; 1..K。时间复杂度为O&#xff08;n2k2&#xff09;。

而如果观察第一个图&#xff0c;我们还可以得到一种状态表示方式。设F[I,J]表示把I划分成J份的划分方案数&#xff0c;则有F[I,J] &#61; F[I-J,K] &#xff0c;其中K &#61; 0..J。时间复杂度为O&#xff08;nk2&#xff09;。

又由于F[I,J]&#61;F[I-J,K]&#xff08;K &#61; 0..J&#xff09;&#61;F[I-J,K]&#xff08;K &#61; 0..J-1&#xff09;&#43;F[I-J,J] &#61; F[I-1,J-1]&#43;F[I-J,J]&#xff0c;这样就把时间复杂度降为O&#xff08;nk&#xff09;。从另外一个角度想&#xff0c;我们在第一个图中“截去底边”&#xff0c;由于存在一个划分方案中含1的情况&#xff0c;我们无法确定在“截去底边”之后要把I-J分为几个数&#xff0c;那么不妨将划分方案中含1的情况单独列出来讨论&#xff0c;直接得到F[I,J] &#61; F[I-1,J-1]&#43;F[I-J,J]

对于第1个小问题的答案是∑F[N,I]&#xff08;I &#61; 1..N&#xff09;&#xff0c;第2个小问题的答案显然是F[N,K]&#xff0c;而第3个小问题的答案则是∑F[N,I]&#xff08;I &#61; 1..K&#xff09;&#xff0c;考虑上面旋转90度之后的图&#xff0c;你会发现&#xff0c;F[N,I]集合中的最高高度均为I&#xff0c;即将n划分成最大数为I的方案数。

最后来看第4个小问题&#xff0c;就是第2个小问题的分奇偶版本&#xff0c;那么设F[I,J]表示把I划分成J个奇数的划分方案数&#xff0c;G[I,J] 表示把I划分成J个偶数的划分方案数。那么还是用“截去底边”的思想&#xff0c;显然有G[I,J] &#61; F[I-J,J]。但F[I,J]却不是直接等于G[I-J,J]&#xff0c;因为这里又存在一个划分方案中含1的情况&#xff0c;同样将划分方案中含1的情况单独列出来讨论&#xff0c;则有F[I,J] &#61; G[I-J,J] &#43; F[I-1,J-1]。最后的答案就是∑F[N,I]&#xff08;I &#61; 1..N&#xff09;&#xff0c;时间复杂度为O(n2)

 

#include
#include

#include
using namespace std;const int maxn &#61; 51;int n,k;
int f[maxn][maxn], g[maxn][maxn];
int f1[maxn][maxn], f2[maxn][maxn];int main () {int i, j;int ans1, ans2, ans3, ans4, ans5;f1[0][0] &#61; 1;for (i &#61; 1; i )for (j &#61; 1; j <&#61; i; j &#43;&#43;)f1[i][j]&#61;f1[i-j][j]&#43;f1[i-1][j-1];f[0][0] &#61; g[0][0] &#61; 1;for (i &#61; 1; i )for (j &#61; 1; j <&#61; i; j &#43;&#43;){g[i][j] &#61; f[i - j][j];f[i][j] &#61; f[i - 1][j - 1] &#43; g[i - j][j];}for (i &#61; 0; i )f2[i][0] &#61; 1;for (i &#61; 1; i )for (j &#61; 1; j ){f2[i][j] &#61; f2[i - 1][j];if (j - i >&#61; 0)f2[i][j] &#43;&#61; f2[i - 1][j - i];}while (scanf ("%d %d", &n, &k) !&#61; EOF){ans1 &#61; ans2 &#61; ans3 &#61; ans4 &#61; ans5 &#61; 0;for (i &#61; 1; i <&#61; n; i &#43;&#43;)ans1 &#43;&#61; f1[n][i];ans2 &#61; f1[n][k];for (i &#61; 1; i <&#61; k; i &#43;&#43;)ans3 &#43;&#61; f1[n][i];for (i &#61; 1; i <&#61; n; i &#43;&#43;)ans4 &#43;&#61; f[n][i];ans5 &#61; f2[n][n];printf ("%d\n%d\n%d\n%d\n%d\n\n", ans1, ans2, ans3, ans4, ans5);}return 0;
}

 



推荐阅读
  • 本文详细探讨了KMP算法中next数组的构建及其应用,重点分析了未改良和改良后的next数组在字符串匹配中的作用。通过具体实例和代码实现,帮助读者更好地理解KMP算法的核心原理。 ... [详细]
  • 题目描述:给定n个半开区间[a, b),要求使用两个互不重叠的记录器,求最多可以记录多少个区间。解决方案采用贪心算法,通过排序和遍历实现最优解。 ... [详细]
  • 扫描线三巨头 hdu1928hdu 1255  hdu 1542 [POJ 1151]
    学习链接:http:blog.csdn.netlwt36articledetails48908031学习扫描线主要学习的是一种扫描的思想,后期可以求解很 ... [详细]
  • 本题探讨了一种字符串变换方法,旨在判断两个给定的字符串是否可以通过特定的字母替换和位置交换操作相互转换。核心在于找到这些变换中的不变量,从而确定转换的可能性。 ... [详细]
  • C++实现经典排序算法
    本文详细介绍了七种经典的排序算法及其性能分析。每种算法的平均、最坏和最好情况的时间复杂度、辅助空间需求以及稳定性都被列出,帮助读者全面了解这些排序方法的特点。 ... [详细]
  • 本文探讨了如何在给定整数N的情况下,找到两个不同的整数a和b,使得它们的和最大,并且满足特定的数学条件。 ... [详细]
  • 优化ListView性能
    本文深入探讨了如何通过多种技术手段优化ListView的性能,包括视图复用、ViewHolder模式、分批加载数据、图片优化及内存管理等。这些方法能够显著提升应用的响应速度和用户体验。 ... [详细]
  • 火星商店问题:线段树分治与持久化Trie树的应用
    本题涉及编号为1至n的火星商店,每个商店有一个永久商品价值v。操作包括每天在指定商店增加一个新商品,以及查询某段时间内某些商店中所有商品(含永久商品)与给定密码值的最大异或结果。通过线段树分治和持久化Trie树来高效解决此问题。 ... [详细]
  • 本文探讨了Hive中内部表和外部表的区别及其在HDFS上的路径映射,详细解释了两者的创建、加载及删除操作,并提供了查看表详细信息的方法。通过对比这两种表类型,帮助读者理解如何更好地管理和保护数据。 ... [详细]
  • 1:有如下一段程序:packagea.b.c;publicclassTest{privatestaticinti0;publicintgetNext(){return ... [详细]
  • 本文介绍如何利用动态规划算法解决经典的0-1背包问题。通过具体实例和代码实现,详细解释了在给定容量的背包中选择若干物品以最大化总价值的过程。 ... [详细]
  • 本文介绍了Java并发库中的阻塞队列(BlockingQueue)及其典型应用场景。通过具体实例,展示了如何利用LinkedBlockingQueue实现线程间高效、安全的数据传递,并结合线程池和原子类优化性能。 ... [详细]
  • IneedtofocusTextCellsonebyoneviaabuttonclick.ItriedlistView.ScrollTo.我需要通过点击按钮逐个关注Tex ... [详细]
  • 本章将深入探讨移动 UI 设计的核心原则,帮助开发者构建简洁、高效且用户友好的界面。通过学习设计规则和用户体验优化技巧,您将能够创建出既美观又实用的移动应用。 ... [详细]
  • 本文详细解析了Python中的os和sys模块,介绍了它们的功能、常用方法及其在实际编程中的应用。 ... [详细]
author-avatar
8o断情戒爱o8
这个家伙很懒,什么也没留下!
PHP1.CN | 中国最专业的PHP中文社区 | DevBox开发工具箱 | json解析格式化 |PHP资讯 | PHP教程 | 数据库技术 | 服务器技术 | 前端开发技术 | PHP框架 | 开发工具 | 在线工具
Copyright © 1998 - 2020 PHP1.CN. All Rights Reserved | 京公网安备 11010802041100号 | 京ICP备19059560号-4 | PHP1.CN 第一PHP社区 版权所有