【发布时间】:2015-10-22 21:53:11
【问题描述】:
我在比赛的某个地方发现了这个问题,但还没有提出解决方案。
这个男孩有苹果,放在盒子里。一盒不超过N/2。 他能用多少种方法把糖果装进盒子里。
所以我想做的是使用 DP 实现解决方案。这是我的代码:
#include <iostream>
#include <cmath>
#include <cstring>
#include <algorithm>
#include <unistd.h>
#include <vector>
#define size 1002
using namespace std;
long long a[size][size];
int n, k;
int main()
{
cin >> n >> k;
int kk = n/2;
for(int i = 0; i <= k; ++i)
a[0][i] = 1;
a[0][0] = 0;
for(int i = 0; i <= kk; ++i)
a[i][1] = 1;
for(int i = 1; i <= n; ++i) {
for(int j = 2; j <= k; ++j) {
int index = 0;
long long res = 0;
while(1) {
res += a[i-index][j - 1];
index += 1;
if(index == kk + 1 || i-index < 0)
break;
}
a[i][j] = res;
}
}
cout << a[n][k] << endl;
}
但问题是我们有大量的输入,例如:
2 ≤ N ≤ 1000 是糖果的数量,N - 偶数; 2 ≤ S ≤ 1000 - 是小盒子的数量。
因此,对于像 N = 1000 和 S = 1000 这样的输入,我必须花费 5*10^8 次操作。而且数字很大,所以我必须使用 BigInteger 算术?
也许有算法可以在线性时间内解决问题?感谢并为我的英语感到抱歉!
【问题讨论】:
-
您的代码对于较小的输入是否给出了正确的结果?
-
@tobi303 是的,该解决方案适用于较小的输入。
-
看看this article 的最后一行,它给出了一个封闭的公式来计算数字(将(
k,m,R)替换为(N,@ 987654327@,(N/2)), resp.)。 -
我猜“在一个小盒子里放的糖果不超过 N/2”应该是“没有小盒子里应该有超过 N/2 个糖果”?
标签: c++ algorithm dynamic-programming combinatorics