题目链接:https://www.dotcpp.com/oj/problem2354.html

    体会:尝试了具有返回值dfs()函数的设计,以及强化了搜索问题的可行性、最优性的理解

    1. import java.util.*;
    2. public class Test{
    3. public static int[] arr;
    4. public static int cnt = 0; //记录长度<=50的小木棍数量
    5. public static int sum = 0; //记录所有长度<=50的小木棍的长度之和
    6. public static boolean[] visited; //标记小木棍的使用状态
    7. public static boolean dfs(int targetCount, int nowCount, int nowSum, int len, int index){
    8. //targetCount: 需要拼凑的木棍数量
    9. //nowCount: 目前已经拼凑的数量
    10. //nowSum: 当前由若干小木棍拼凑的长度
    11. //len: 此次枚举的木棍长度
    12. //index: 遍历的下标
    13. if(nowCount == targetCount){ //所有小木棍恰好能拼凑出 targetCount根长度为len的木棍
    14. return true;
    15. }
    16. if(nowSum == len){ //已经拼凑出一根长度为len的木棍,接着往下尝试
    17. return dfs(targetCount, nowCount + 1, 0, len, cnt);
    18. }
    19. for(int i = index; i >= 0; i--){
    20. if(!visited[i] && nowSum + arr[i] <= len){ //剪枝2:保证小木棍拼凑的长度 <= len
    21. visited[i] = true;
    22. if(dfs(targetCount, nowCount, nowSum + arr[i], len, i-1)){ //此处记得将dfs()的结果return
    23. return true;
    24. }
    25. visited[i] = false;
    26. //剪枝3:如果当前arr[i]尝试失败后(因为只有失败后才回溯到此处),证明arr[i]对当前的结果无作用,直接跳过
    27. while(i > 0 && arr[i] == arr[i-1]) i--;
    28. }
    29. }
    30. return false;
    31. }
    32. public static void main(String[] args) {
    33. Scanner sc = new Scanner(System.in);
    34. int n = sc.nextInt();
    35. arr = new int[n+1];
    36. visited = new boolean[n+1];
    37. int num;
    38. for(int i = 1; i <= n; i++){
    39. num = sc.nextInt();
    40. if(num <= 50){ //长度>50的小木棍全都抛弃,不然AC不了
    41. arr[++cnt] = num;
    42. sum += num;
    43. }
    44. }
    45. //按从小到大排序,然后逆序遍历
    46. Arrays.sort(arr, 1, cnt + 1);
    47. //枚举切割前木棍的长度,其范围为[最长的小木棍长度,所有小木棍长度之和]
    48. //注意这里说的小木棍都是指长度<=50的
    49. for(int len = arr[cnt]; len <= sum; len++){
    50. //剪枝1:sum必须能整除木棍的长度
    51. if(sum % len == 0){
    52. Arrays.fill(visited, false);
    53. //切割前木棍的数量
    54. int k = sum / len;
    55. //我们需要去利用现有的小木棍,使其能刚好拼凑出k根长度为len的木棍
    56. //如果当前的方案能够生效,必然是最小的长度
    57. if(dfs(k, 0, 0, len, cnt)){
    58. System.out.println(len);
    59. return;
    60. }
    61. }
    62. }
    63. }
    64. }