成长轨迹58 【ACM算法之路 百炼poj.grids.cn】【递归】【1664:放苹果】
2012-02-25 15:14
357 查看
题目http://poj.grids.cn/practice/1664
真心是一道很经典很经典的题目,还是单独列出来
离散数学学过划分,但是那是集合划分,这道题是整数划分。
整数划分的思想如下:
整数划分问题是将一个正整数n拆成一组数连加并等于n的形式,且这组数中的最大加数不大于n。
如6的整数划分为
6
5 + 1
4 + 2, 4 + 1 + 1
3 + 3, 3 + 2 + 1, 3 + 1 + 1 + 1
2 + 2 + 2, 2 + 2 + 1 + 1, 2 + 1 + 1 + 1 + 1
1 + 1 + 1 + 1 + 1 + 1
共11种。
【dfs代码】
View Code
下面介绍一种通过递归方法得到一个正整数的划分数。
递归函数的声明为 int deal(int m, int n);其中m为要划分的正整数,n是划分中的最大加数(当n > m时,最大加数为m),
1 当m = 0 或 n = 1时,deal的值为1,可根据上例看出,只有一个划分1 或 1 + 1 + 1 + 1 + 1 + 1
可用程序表示为if(n == 1 || m == 0) return 1;
2 下面看一看m 和 n的关系。它们有三种关系
(1) n > m
在整数划分中实际上最大加数不能大于m,因此在这种情况可以等价为deal(m, m);
可用程序表示为if(n > m) return deal(m, m);
(2) n < m 这是最一般的情况,在划分的大多数时都是这种情况。
从上例可以看出,设n = 4,那deal(6, 4)的值是最大加数小于4划分数和整数2的划分数的和。
即 deal(6,4) = deal(6,3) + deal(2,4)
因此,此时deal(n, m)可表示为deal(m, n - 1) + deal(m - n, n)
(3) m = n
这种情况可用递归表示为deal(m, n - 1) + 1,从以上例子中可以看出,就是最大加数为6和小于6的划分之和
用程序表示为if(m == n) return (deal(m, n - 1) + 1);
我们发现其实也可以满足上面(2)所推导的公式
按照整数划分的思想,将一个整数划分为若干(x<=m) 整数,按由大到小逐级递减的顺序排列, 这样保证了不会出现 5,1,1 和 1,5,1 这种相同的情况,根据这样的思路来建立一个递归关系。
【ac代码】
真心是一道很经典很经典的题目,还是单独列出来
离散数学学过划分,但是那是集合划分,这道题是整数划分。
整数划分的思想如下:
整数划分问题是将一个正整数n拆成一组数连加并等于n的形式,且这组数中的最大加数不大于n。
如6的整数划分为
6
5 + 1
4 + 2, 4 + 1 + 1
3 + 3, 3 + 2 + 1, 3 + 1 + 1 + 1
2 + 2 + 2, 2 + 2 + 1 + 1, 2 + 1 + 1 + 1 + 1
1 + 1 + 1 + 1 + 1 + 1
共11种。
【dfs代码】
View Code
#include"iostream" using namespace std; int count=0; int M,m,n; void DFS(int k, int s,int t){ if( s==n ){ if(t==m) count++; return ; } int i; for(i=k;i>=0; i--){ if( t + i <= m ) { DFS(i, s+1, t+i); } else { continue; } } } int main() { int i; scanf("%d",&M); while(M--) { count=0; scanf("%d %d",&m, &n); for(i=m;i>=0;i--) { DFS(i,1,i); } printf("%d\n",count); } return 0; }
下面介绍一种通过递归方法得到一个正整数的划分数。
递归函数的声明为 int deal(int m, int n);其中m为要划分的正整数,n是划分中的最大加数(当n > m时,最大加数为m),
1 当m = 0 或 n = 1时,deal的值为1,可根据上例看出,只有一个划分1 或 1 + 1 + 1 + 1 + 1 + 1
可用程序表示为if(n == 1 || m == 0) return 1;
2 下面看一看m 和 n的关系。它们有三种关系
(1) n > m
在整数划分中实际上最大加数不能大于m,因此在这种情况可以等价为deal(m, m);
可用程序表示为if(n > m) return deal(m, m);
(2) n < m 这是最一般的情况,在划分的大多数时都是这种情况。
从上例可以看出,设n = 4,那deal(6, 4)的值是最大加数小于4划分数和整数2的划分数的和。
即 deal(6,4) = deal(6,3) + deal(2,4)
因此,此时deal(n, m)可表示为deal(m, n - 1) + deal(m - n, n)
(3) m = n
这种情况可用递归表示为deal(m, n - 1) + 1,从以上例子中可以看出,就是最大加数为6和小于6的划分之和
用程序表示为if(m == n) return (deal(m, n - 1) + 1);
我们发现其实也可以满足上面(2)所推导的公式
按照整数划分的思想,将一个整数划分为若干(x<=m) 整数,按由大到小逐级递减的顺序排列, 这样保证了不会出现 5,1,1 和 1,5,1 这种相同的情况,根据这样的思路来建立一个递归关系。
【ac代码】
#include <stdio.h> #include <stdlib.h> int deal(int m,int n) { if(m==0||n==1) return 1; else if(n>m) return deal(m,m); else return deal(m,n-1)+deal(m-n,n); } int main() { int t; scanf("%d",&t); for(int i=0;i<t;i++) { int m,n; scanf("%d %d",&m,&n); printf("%d\n",deal(m,n)); } return 0; }
相关文章推荐
- 成长轨迹59 【ACM算法之路 百炼poj.grids.cn】【递归】【2694:逆波兰表达式】
- 成长轨迹60 【ACM算法之路 百炼poj.grids.cn】【递归】【2756:二叉树】
- 成长轨迹57 【ACM算法之路 百炼poj.grids.cn】【递归】【2754、2816、2753、】
- 成长轨迹42 【ACM算法之路 百炼poj.grids.cn】【数值转换】【2972、2798、2735、2734、2973】
- 成长轨迹50 【ACM算法之路 百炼poj.grids.cn】【字符串处理】【2974:487-3279】
- 成长轨迹51 【ACM算法之路 百炼poj.grids.cn】【字符串处理】【2744:子串】
- 成长轨迹61 【ACM算法之路 百炼poj.grids.cn】【动态规划】【2806、1661、2757】
- 成长轨迹52 【ACM算法之路 百炼poj.grids.cn】【字符串处理】【2743:字符串判等】
- 成长轨迹53 【ACM算法之路 百炼poj.grids.cn】【简单枚举】【2747、2810、2692、2977】
- 成长轨迹54 【ACM算法之路 百炼poj.grids.cn】【简单枚举】【2739:计算对数】
- 成长轨迹44 【ACM算法之路 百炼poj.grids.cn】【字符串处理】【2799、2976、2975、2742】
- 成长轨迹55 【ACM算法之路 百炼poj.grids.cn】【简单枚举】【2812:恼人的青蛙】
- 成长轨迹56 【ACM算法之路 百炼poj.grids.cn】【简单枚举】【2811:熄灯问题】
- 成长轨迹45 【ACM算法之路 百炼poj.grids.cn】【字符串处理】【2797:最短前缀】
- 成长轨迹46 【ACM算法之路 百炼poj.grids.cn】【字符串处理】【2804:词典】
- 成长轨迹47 【ACM算法之路 百炼poj.grids.cn】【字符串处理】【2820:古代密码】
- 成长轨迹48 【ACM算法之路 百炼poj.grids.cn】【字符串处理】【2818:密码】
- 成长轨迹43 【ACM算法之路 百炼poj.grids.cn】【数值转换】【2765:八进制小数】
- 成长轨迹49 【ACM算法之路 百炼poj.grids.cn】【字符串处理】【2819:W的密码】
- 嵌入式成长轨迹58 【Zigbee项目】【CC2430基础实验】【看门狗模式】