题目:将N个鸡蛋装入M个篮子,保证每个篮子都不能为空,且对于任意给定的小于N的整数,均有几个篮子的鸡蛋个数和与之相等,请给出所有可能的装法。 设用f(N, M)表示该问题的解决方案,设想将N/2个鸡蛋装入前面i个篮子里,则后面的M-i个篮子中鸡蛋可以任意排列,只要保证不为空即可,设g(n, m)表示该排列,其中n表示鸡蛋个数,m表示篮子个数。所以,初始问题f(N,M) = f(N/2, i) U g(N - N / 2, M - i);其中i的取值可以为[up_log(N/2), M-1], up_log(n)表示对n取对数并向上取整。 g(n, m) 也是一个递归函数,具体见如下实现:
Back
#include <stdio.h>
#include <stdlib.h>
#define MAX 100
#define RS_SIZE 1000
int eggs[MAX];
int rs[RS_SIZE][MAX];
int label = 1;
int up_log (int n);
void g (int eggs, int start, int end, int cons_m);
void printResult (int end);
void solution (int N_eggs, int M_basket, int cons_m);
void resume (int end);
void sort (int a[], int n);
int find (int a[], int rs[][MAX], int end, int label);
int up_log (int n) {
int i = 0;
int k = 1;
while (k < n) {
k <<= 1;
i++;
}
return i;
}
void solution (int N, int M, int cons_m) {
int i;
int k;
if (M == 1 && N > 1) {
resume(M);
return;
}
if ( M < up_log (N) ) {
resume(M);
return;
}
if (M > N) {
resume(M);
return;
}
if ( M == N ) {
for (i = 0; i < M; i++)
eggs[i] = 1;
if (M == cons_m)
printResult (cons_m);
return;
}
if (N == M + 1) {
for (i = 0; i < M; i++)
eggs[i] = 1;
eggs[M - 1] = 2;
if (M == cons_m)
printResult (cons_m);
return;
}
k = (up_log(N / 2)) ? up_log( N / 2) : 1;
for (i = k; i < M; i++) {
solution (N / 2, i, cons_m);
g (N - N / 2, i, M - 1, cons_m);
}
}
void g (int eggs_num, int start, int end, int cons_m) {
int i;
if (start > end)
return;
if (!eggs_num)
return;
if ( start == end ) {
eggs[end] = eggs_num;
if (eggs[0] && (end + 1) == cons_m)
printResult (cons_m);
return;
}
if (end - start + 1 > eggs_num)
return;
else {
for (i = 1; i <= eggs_num -end + start; i++) {
eggs[start] = i;
g (eggs_num - i, start + 1, end, cons_m);
}
}
}
void printResult (int end) {
int i;
int in_rs_array = 0;
int tmp[MAX];
for (i = 0; i < end; i++)
tmp[i] = eggs[i];
sort (tmp, end);
if (label > 1)
in_rs_array = find (tmp, rs, end, label - 1);
if (!in_rs_array) {
printf ("Method %d: ", label);
for (i = 0; i < end; ) {
printf ("%4d", tmp[i]);
rs[label - 1][i] = tmp[i];
if ( ++i % 10 == 0 )
printf ("/n");
}
printf ("/n");
label++;
}
}
void resume (int end) {
int i;
for (i = 0; i < end; i++)
eggs[i] = 0;
}
void sort (int a[], int n) {
int i, j;
int temp;
int swap = 1;
for (i = 0; i < n - 1; i++) {
swap = 0;
for (j = 0; j < n - i - 1; j++)
if (a[j + 1] < a[j]) {
temp = a[j];
a[j] = a[j + 1];
a[j + 1] = temp;
swap = 1;
}
if (!swap)
break;
}
}
int find (int a[], int rs[][MAX], int end, int label) {
int i, j;
for (i = 0; i < label; i++)
for (j = 0; j < end; j++) {
if (a[j] == rs[i][j] && j == end - 1)
return 1;
if (a[j] != rs[i][j])
break;
}
return 0;
}
int main (int argc, char **argv) {
int eggs, basket;
printf ("Please input number of eggs and baskets:/n");
scanf("%d%d", &eggs, &basket);
resume (basket);
solution (eggs, basket, basket);
if ( label == 1)
printf ("No solution found!/n");
exit (0);
}
Top