就是一堆数字中可以组成多少个9(其实也可以是其他任意的数字),刚开始看到这题的时候脑子是懵的,于是就参考了一下一位大神的代码,但他代码里有两个标志数组,我看了就很迷糊,而且dfs的返回值是一个bool类型,很是不理解(是我菜了),于是我只好自己慢慢写,没想到最后只用一个标志数组也还是过了。就是代码量有点长,但这都不是问题,好理解就行了(doge)。
题目描述
小明最近遇到一个这样的问题:随机生成n个1-9之间的数字(数字可能有重复),每次可以从中选取若干个数字,使得这些数字的和等于9,每一个随机生成的数字只能选取一次。
请问如何选取可以使得组成的9的个数最多,请输出最多可以得到的9的个数。
输入
输入n个1-9之间的正整数,两两之间用空格隔开。(n<=20)
输出
输出最多可以得到的9的个数。
样例输入
1 4 5 6 1 2 2 3 7 8 9
样例输出
5
#include#include using namespace std; int flag[25], arr[25], len, ans; int num;//记录还有多少个可以选的数 int tmp[25];//记录以选数的下标 int n; void dfs(int m,int pos,int sum)//m 记录选数的个数 pos 是记录该从哪个位置找数 { if (sum == 0 && m == len) { for (int i = 0; i < m; i++) { if (flag[tmp[i]] == 1)//如果这一组数里有一个数不行,那整组数废了 return; } for (int i = 0; i < m; i++) { flag[tmp[i]] = 1; } num -= len; ans++; return; } else if (m == len)//如果已经选了len个数,但sum不等于0也要return return; for (int i = pos; i < n; i++) { if (flag[i] == 0 && sum - arr[i] >= 0) { tmp[m] = i; dfs(m + 1, i + 1, sum - arr[i]); } else if (sum - arr[i] < 0)//arr[i]后面的数必定大于等于arr[i] return; } } int main() { while (~scanf("%d", arr + n))//这里选择scanf而不是cin是因为scanf快一点,在某些题中cin会超时,所以要习惯scanf { if (arr[n] == 9) { n--;//这个数已经用了 ans++;//答案加一 } n++; char c = getchar(); if (c == 'n') break; } num = n; sort(arr, arr + n);//排序一下,可以比较好的跳出循环递归,否则会超时 len = 2;//len是我们选的数的个数,因为不知道要选多少个数,所以只好枚举 while (len <= num) { dfs(0, 0, 9); len++; } printf("%dn", ans); return 0; }
相信大佬会觉得我的过程太繁琐,勿喷蟹蟹!!!!



