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

推荐订阅源

Apple Machine Learning Research
Apple Machine Learning Research
博客园_首页
G
Google Developers Blog
aimingoo的专栏
aimingoo的专栏
罗磊的独立博客
博客园 - 【当耐特】
M
MIT News - Artificial intelligence
D
Docker
博客园 - 三生石上(FineUI控件)
博客园 - 司徒正美
人人都是产品经理
人人都是产品经理
博客园 - 叶小钗
月光博客
月光博客
S
SegmentFault 最新的问题
Jina AI
Jina AI
Blog — PlanetScale
Blog — PlanetScale
奇客Solidot–传递最新科技情报
奇客Solidot–传递最新科技情报
博客园 - Franky
L
LangChain Blog
钛媒体:引领未来商业与生活新知
钛媒体:引领未来商业与生活新知
Microsoft Azure Blog
Microsoft Azure Blog
阮一峰的网络日志
阮一峰的网络日志
让小产品的独立变现更简单 - ezindie.com
让小产品的独立变现更简单 - ezindie.com
Last Week in AI
Last Week in AI

博客园 - 左右间

幻方阵 关于在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较大,马上就内存溢出。