关于N个鸡蛋M个篮子

题目:将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
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 2
    评论
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值