一道算法题目的解法

一道算法题目的解法

有这样一道算法题目:144张牌放到若干的盒子中, 每个盒子中放1040张, 问有多少种放法?(不考虑顺序)

分析

144/10=14.4144/40=3.6可得, 盒子的数量最少为4 最多为14.

假设有n个盒子(4<=n<=14,每个盒子中分别放a1, a2, …, an张牌, 由于不考虑顺序, 不妨设a1<=a2<= … <=an.

然后可以根据盒子的数量进行穷举, 从而得出答案。

考虑到14个盒子的情况, 30^14是个很可观的数字, 为了提高算法的效率, 需要计算ai(1<=i<=n)的最大和最小值。

容易得出

ai最小的情况是

a1=…=ai, ai+1=…=an=40

min(ai)=(144 – (n-i)*40)/i

ai最大的情况

a1=min(a1) a2= min(a2)…ai-1= min(ai-1), ai= ai+1=…=an

max(ai)=(144-min(a1)-min(a2)-...-min(ai-1))/i

 

使用深度优先搜索法的程序如下

#include <stdio.h>

#include <stdlib.h>

 

#define COUNT 144

#define MAXVAL 40

#define MINVAL 10

 

int count = 0;

 

int** minvals;

int** maxvals;

 

void get_min_max_vals () {

  int i;

  int j;

  int k;

  int min, max;

  int temp;

  minvals = (int**) malloc (11 * sizeof(int*));

  maxvals = (int**) malloc (11 * sizeof(int*));

  for (i = 4; i < 15; i++) {

    minvals[i - 4] = (int*) malloc (i * sizeof(int));

    maxvals[i - 4] = (int*) malloc (i * sizeof(int));

    for (j = 0; j < i; j++) {

      min = (COUNT - MAXVAL * (i - j - 1))/(j + 1);

      minvals[i - 4][j] = min > MINVAL? min: MINVAL;

      temp = 0;

      for (k = 0; k < j; k++) {

     temp += minvals[i - 4][k];

      }

      max = (COUNT - temp) / (i - j);

      maxvals[i - 4][j] = max > MAXVAL ? MAXVAL: max;

    }

  }

}

 

void calc (int cur, int total, int* vals) {

  int i;

  int from;

  int last = COUNT;

 

  if (cur == total){

    for (i = 0; i < cur; i++) {

      last -= vals[i];

    }

    if ((last >= vals[cur - 1]) && (last <= MAXVAL)) {

      vals[cur] = last;

      count ++;

    }

    return;

  }

  if (0 == cur) {

    from = minvals[total - 3][cur];

  } else {

    from = minvals[total - 3][cur] > vals[cur - 1] ? minvals[total - 3][cur]: vals[cur - 1];

  }

  for (i = from; i <= maxvals[total - 3][cur]; i++) {

    vals[cur] = i;

    calc (cur + 1, total, vals);

  }

}

 

 

int main() {

  int j;

  int* vals;

  int totalcount;

  get_min_max_vals();

 

  for (j = 4; j < 15; j++) {

    count = 0;

    vals = (int*) malloc (j * sizeof(int));

    calc (0, j - 1, vals);

    printf ("%d boxes: count=%d/n",j, count);

    totalcount += count;

    free(vals);

  }

  printf ("total=%d/n", totalcount);

  for (j = 0; j < 11; j++) {

    free(minvals[j]);

    free(maxvals[j]);

  }

  free(minvals);

  free(maxvals);

  return 0;

}

 

 
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值