回溯算法

120 阅读1分钟

1、运用场景

  • 回溯算法:通过穷举所有可能的解来找出所有满足条件的解的算法
  • 复杂度:通常为指数级别
  • 优缺点:
      • 缺点:时间复杂度高,递归深度过大,可能会导致栈溢出等问题
      • 优点:灵活性高、完备性、可以解决最优化问题

2、流程图

image.png

3、代码示例

import java.util.ArrayList;
import java.util.List;

/**
*在Java中,使用回溯算法来实现资源对象列表的排列组合,并满足特定的条件(如资源数量在1-3之间,总金**额在100-200之间,且每个方案必须包含资源A,不包含资源B)
*/
public class ResourceCombinationGenerator {
    
 public class Resource {
        String name;
        int amount;

        public Resource(String name, int amount) {
            this.name = name;
            this.amount = amount;
        }

        @Override
        public String toString() {
            return name + "(" + amount + ")";
        }
    }

    private static final String RESOURCE_A = "A";
    private static final String RESOURCE_B = "B";

    public void backtrack(int start,List<Resource> resources,List<Resource> currentCombination,List<List<Resource>> result) {
        if (currentCombination.size() > 3) {
            return ; // 超过3个资源,结束回溯
        }

        if (!currentCombination.isEmpty() &&
                currentCombination.size() <= 3 &&
                currentCombination.stream().mapToInt(resource -> resource.amount).sum() >= 100 &&
                currentCombination.stream().mapToInt(resource -> resource.amount).sum() <= 200 &&
                currentCombination.stream().anyMatch(resource -> RESOURCE_A.equals(resource.name)) &&
                !currentCombination.stream().anyMatch(resource -> RESOURCE_B.equals(resource.name))) {
            // 满足条件,添加到结果列表
            result.add(new ArrayList<>(currentCombination));
        }

        for (int i = start; i < resources.size(); i++) {
            Resource resource = resources.get(i);

            if (RESOURCE_B.equals(resource.name)) {
                continue; // 跳过资源B
            }

            currentCombination.add(resource);
            backtrack(i + 1,resources,currentCombination,result); // 继续向下搜索
            currentCombination.remove(currentCombination.size() - 1); // 回溯,移除最后一个添加的资源
        }
    }

    @Test
    public  void main() {
        List<Resource> resources = new ArrayList<>();
        resources.add(new Resource("A", 50));
        resources.add(new Resource("B", 30)); // 这个资源将不会被包括在任何组合中
        resources.add(new Resource("C", 60));
        resources.add(new Resource("D", 90));
        resources.add(new Resource("E", 120));
        List<List<Resource>> combinations=new ArrayList<>();
        backtrack(0,resources,new ArrayList<>(),combinations);
        System.out.println(combinations);
    }

}