其他
算法面试题:放苹果
The following article is from 小K算法 Author 小K算法
注:5,1,1和1,5,1是同一种分法,且1<=M,N<=10。
02分析
苹果比盘子多
苹果比盘子少
苹果和盘子数量相同
其实这个问题就是把M个苹果分成不超过N堆,总共有多少种分法。所以可先按每堆苹果数量排序,依次比较每一堆的苹果,如果所有堆都一样才是相同的分法。这也就意味着堆数肯定相同,然后排序后每一堆也相同,这样才算是相同的分法。
堆数不同一定是不同的分法。
堆数相同,但排序后,有超过一堆的数量不相同
如下,堆数不同,所以是不同的分法。
03划分子问题
04算法建模
m<n,把m个苹果刚好分成n堆,明显是不可能的,所以f[m,n]=0
m=n,把m个苹果刚好分成m堆,明显只有一种情况,就是每一堆1个,所以f[m,n]=1
m>n,第3小节已经说明,这种情况就划分成子问题,先在每一堆放1个,剩下的再依次分成1堆,2堆...n堆,所以f[m,n]=f[m-n,1]+f[m-n,2]+...+f[m-n,n]
05代码实现
if (f[m][n] != -1) return f[m][n];
if (m < n) {
f[m][n] = 0;
return f[m][n];
}
if (m == n || n == 1) {
f[m][n] = 1;
return f[m][n];
}
f[m][n] = 0;
for (int i = 1; i <= n; ++i) {
f[m][n] += solve(m - n, i);
}
return f[m][n];
}
int n, m;
// 初始化为-1
memset(f, 0xff, sizeof(f));
cin >> m >> n;
int ans = 0;
for (int i = 1; i <= n; ++i) {
ans += solve(m, i);
}
cout << ans << endl;
return 0;
}
06番外篇
有空盘子
没有空盘子
if (m < 0) return 0;
if (m == 0 || n == 1) return 1;
return solve(m - n, n) + solve(m, n - 1);
}
07整数划分
把一个整数n写成多个大于等于1小于等于它本身的整数的和,即n=m1+m2+...,则[m1,m2...]构成的一个集合称为n的一个划分,那么总共有多少种不同的划分呢?
你品,你细品,这不就是同一个问题吗,只不过我们把它抽象成了一个纯数学问题,这就是很经典的整数划分问题。
08总结
- EOF -
关注「程序员的那些事」加星标,不错过圈内事
点赞和在看就是最大的支持❤️