惯性聚合 高效追踪和阅读你感兴趣的博客、新闻、科技资讯
阅读原文 在惯性聚合中打开

推荐订阅源

Simon Willison's Weblog
Simon Willison's Weblog
G
Google Developers Blog
Spread Privacy
Spread Privacy
I
InfoQ
V
V2EX
S
Schneier on Security
小众软件
小众软件
C
CERT Recently Published Vulnerability Notes
博客园 - 聂微东
奇客Solidot–传递最新科技情报
奇客Solidot–传递最新科技情报
Stack Overflow Blog
Stack Overflow Blog
T
Threat Research - Cisco Blogs
L
Lohrmann on Cybersecurity
Recent Announcements
Recent Announcements
Cyber Security Advisories - MS-ISAC
Cyber Security Advisories - MS-ISAC
Attack and Defense Labs
Attack and Defense Labs
云风的 BLOG
云风的 BLOG
The Hacker News
The Hacker News
S
SegmentFault 最新的问题
C
Cybersecurity and Infrastructure Security Agency CISA
NISL@THU
NISL@THU
OSCHINA 社区最新新闻
OSCHINA 社区最新新闻
GbyAI
GbyAI
Latest news
Latest news
S
Secure Thoughts
Project Zero
Project Zero
MongoDB | Blog
MongoDB | Blog
I
Intezer
Security Latest
Security Latest
Apple Machine Learning Research
Apple Machine Learning Research
Vercel News
Vercel News
N
Netflix TechBlog - Medium
V2EX - 技术
V2EX - 技术
量子位
T
Threatpost
T
The Blog of Author Tim Ferriss
Y
Y Combinator Blog
T
Tor Project blog
A
Arctic Wolf
Microsoft Security Blog
Microsoft Security Blog
T
The Exploit Database - CXSecurity.com
大猫的无限游戏
大猫的无限游戏
T
Tailwind CSS Blog
freeCodeCamp Programming Tutorials: Python, JavaScript, Git & More
C
Check Point Blog
博客园 - Franky
Google DeepMind News
Google DeepMind News
The Register - Security
The Register - Security
The GitHub Blog
The GitHub Blog
L
LINUX DO - 热门话题

博客园 - 左右间

幻方阵 关于在cmd命令里的路径包含空格的问题 MSE-项目管理知识体系(一) 导论 导入导出EXCEL数据时有关时间的处理 比较简单的导入导出EXCEL数据的方法 使用aspnet_regiis.exe加密web.config文件 如何使用CAML 批量更新SharePoint List Stsadm 详细文档 关于SPList的Update及AllowUnsafeUpdates 关于silverlight文件的结构 关于VS.NET权限不够的问题 关于Web Part中的Tokens. 关于AD搜索的The server is not operational错误 IIS 中 Service Unavailable问题的解决方法 Flex样式控制小记 如何在WebPart的菜单中添加自定义的Verbs. 关于FireFox网址收藏夹的比较酷的应用 SharePoint中传递Search参数的Url的一些研究 关于使用JavaScript触发ASP.NET Validator验证的问题
整数划分问题之寻找 一组不大于M的互异的整数集,使之和等于N。找出可能的整数集的个数。
左右间 · 2009-01-15 · via 博客园 - 左右间

问题分析:

假定N = 1, 则可能的整数集这能为{1}, 所以个数为1。

假定M = 1,N > 1, 则不可能有合适的整数集,所以个数为0。

假定M > N, 则结果集的个数和M = N的一样多, 因为不可能出现比N大的数。

假定M <= N, M > 1, N > 1, 此时我们有两种情况,结果集中包括M, 或者不包括。最终的数量为这两种情况的数量之和。

假定我们用F(N,M)来表示结果集的数量。则有如下表达式:

F(1,M) = 1; M为任意值.
F(N,1) = 0; N > 1.
F(N,M) = F(N,N); M > N.
F(N,M) = F(N - M,M - 1) + F(N,M - 1);M <= N, M > 1, N > 1.

一般有两种方式来解决这种问题,递归和动态规划。

递归方式:

        public static int GetPartitionCount2(int number, int maxElement)
        {
            if (number == 1)
                return 1;
            if (maxElement == 1)
                return 0;

            if (maxElement < number)
                return GetPartitionCount2(number - maxElement, maxElement - 1) + GetPartitionCount2(number, maxElement - 1);
            else
                return 1 + GetPartitionCount2(number, number - 1);
        }

动态规划:
public static int GetPartitionCount1(int number, int maxElement)
        {
            int[,] calculateTable = new int[number + 1, maxElement + 1];

            calculateTable[1, 1] = 1;

            for (int i = 2; i < number + 1; i++)
            {
                calculateTable[i, 1] = 0;
            }

            for (int i = 1; i < maxElement + 1; i++)
            {
                calculateTable[1, i] = 1;
            }

            for (int i = 2; i < maxElement + 1; i++)
            {
                for (int j = 2; j < number + 1; j++)
                {
                    if(i<j)
                        calculateTable[j, i] = calculateTable[j - i, i - 1] + calculateTable[j, i - 1];
                    else if(i>=j)
                        calculateTable[j, i] = 1 + calculateTable[j, j - 1];
                }
            }

            return calculateTable[number, maxElement];
        }

就递归方式而言,最大的不好之处就是递归次数太多,做了太多的冗余计算。

(N,M)          所需时间(ms)    
100,100        250
120,120         1281.3
140,140         6297
160,160         27484.7
180,180         110844.5
200,200         398417.4

相对而言,动态规划效率要高很多,不是一个数量级的。

(N,M)          所需时间(ms)    
1000,1000    46
2000,2000       187.5
3000,3000       593.8
4000,4000       1719.0
5000,5000       3172.3
6000,6000       5657.0
7000,7000    9345.1
8000,8000    13220.6
9000,9000    17736.9
10000,10000    22329.8

但是,在上面的动态规划算法中,有一个致命的地方就是数组分配,
int[,] calculateTable, 如果m,n较大,马上就内存溢出。