題目:已知n個數字構成的非遞增序列,求能從中取出的和為t 的不同組合。
分析:組合數學。組合數生成,這裡利用dfs求解。
生成的過程可全排列相同,每次判斷生成的組合是否之前找到過即可;
這裡只需要保留上次計算的結果,因為新的結果序列上一定小於之前的;
說明:年後的第一題。
#include <stdio.h>
#include <stdlib.h>
int input[13];
int sum_to_end[13];
int ans[13];
int ans_size;
int ans_count;
int save[13];
int dfs(int sum, int now, int s, int n, int deep)
{
if (now == sum) {
int is_new = 1;
if (ans_count) {
is_new = 0;
for (int i = 0; i < deep; ++ i) {
if (ans[i] < save[i]) {
break;
}
if (ans[i] != save[i]) {
is_new = 1;
break;
}
}
}
if (is_new) {
for (int i = 0; i < deep; ++ i) {
ans[i] = save[i];
}
printf("%d",ans[0]);
for (int i = 1; i < deep; ++ i) {
printf("+%d",ans[i]);
}
puts("");
ans_count ++;
ans_size = deep;
}
return 1;
}
for (int i = s; i <= n; ++ i) {
if (sum_to_end[i]+now >= sum && input[i]+now <= sum) {
save[deep] = input[i];
dfs(sum, now+input[i], i+1, n, deep+1);
}
}
return 0;
}
int main()
{
int t, n;
while (~scanf("%d%d",&t,&n) && t+n) {
int count = 0;
for (int i = 1; i <= n; ++ i) {
scanf("%d",&input[i]);
}
sum_to_end[n] = input[n];
for (int i = n-1; i >= 1; -- i) {
sum_to_end[i] = sum_to_end[i+1]+input[i];
}
printf("Sums of %d:\n",t);
ans_count = 0;
dfs(t, 0, 1, n, 0);
if (!ans_count) {
puts("NONE");
}
}
return 0;
}