1. 程式人生 > >發奮忘食,樂以忘優,不知老之將至

發奮忘食,樂以忘優,不知老之將至

一道演算法題目的解法

有這樣一道演算法題目: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;

}