编程题 -- 分组问题,输出公式(一)
编程题:
命令行输入两个整数N 和 P. (N<=P). 程序输出满足以下条件的一系列公式:
公式为: A1*B1 + A2*B2 + ... + An*Bn
要求:
公式需同时满足:
A1*B1 + A2*B2 + ... + An*Bn = N
A1+A2+..+An = P
其中数列: A1 A2 ... An 为 >=1的整数数列.
B1 B2 ... Bn 为 >=1的整数数列,且 满足:Bn>Bn-1
多条公式为并列关系,无输出先后要求.
该程序命名为grouping(分组). 有一批多种颜色的球(数量无限)需装进一个N个格子的包装里.每个包装中只有P种颜色的球.请问这些组合里的重复情况.
比如有 A1个出现B1次+A2个出现B2次.
例如:
输入
grouping 7 5
4*1 + 1*3
3*1 + 2*2
解题思路:(不喜看思路者可直接看代码)
设计一个函数传入N P K S. 函数可递归调用.
N为剩余N值 P为剩余P值 K为最小的B值 S为传入字符串.
题设当输入 7 5时,函数调用为:
F(7,5,1,NULL)
函数尝试 :
5*1 P-5=0, 5*1 < 7 F(7,5,2,NULL) 继续下一个尝试.
4*1 P-4=1 调用 F(7-4*1,5-4,2,"4*1 ") ,递归返回后继续下一个尝试.
3*1 调用 F(4,2,2,"3*1 ")
2*1 调用 F(5,3,2,"2*1 ")
1*1 调用 F(6,4,2,"1*1 ")
返回.
调用: F(7-4*1,5-4,2,"4*1 ") 的解析
F(3,1,2,"4*1 ")
尝试
1*2 P-1=0 ,F(3,1,3,"4*1 ") ---> 输出 4*1 + 1*3
调用 F(4,2,2,"3*1 ")
尝试
2*2=4 ---> 输出 3*1 + 2*2
代码:
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
// 该程序命名为grouping(分组). 有一批多种颜色的球(数量无限)需装进一个N个格子的包装里.每个包装中只有P种颜色的球.请问这些组合里的重复情况.
// 比如有 A1个出现B1次+A2个出现B2次.
// 设每种颜色的球数为maxK. 当对问题出现数量限制时,不需要再修改程序,只需在命令行后面加上限制即可.
int maxK=65536;
void grouping(int N,int P,int K ,char* prestr) {
#define grouping_buf_size 128
// trying: N N-1 N-2 ....
char buf[grouping_buf_size];
for(int i=P;i>0;i--) {
if(prestr==NULL) {
sprintf(buf,"%d*%d",i,K);
}
else {
sprintf(buf,"%s + %d*%d",prestr,i,K);
}
if(P-i==0) {
if(N-i*K == 0) {
printf("%s\n",buf);
}
else if(N-i*K > 0) {
if(K<maxK) grouping(N,P,K+1,prestr);
}
else if(N-i*K < 0) {
}
}
else if(N-i*K>0){
if(K<maxK) grouping(N-i*K,P-i,K+1,buf);
}
}
#undef grouping_buf_size
}
int main(int argc,char** argv) {
if(argc<3) {printf("%s N P [maxK]\n",argv[0]);}
int n=atoi(argv[1]);
int p=atoi(argv[2]);
if(argc=4) maxK=atoi(argv[3]);
grouping(n,p,1,NULL);
return 1;
}
测试:
$ grouping 7 7
7*1
$ grouping 7 6
5*1 + 1*2
$ grouping 7 5
4*1 + 1*3
3*1 + 2*2
$ grouping 7 4
3*1 + 1*4
2*1 + 1*2 + 1*3
1*1 + 3*2
$ grouping 7 3 4
2*2 + 1*3
1*1 + 2*3
1*1 + 1*2 + 1*4