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

    1. import java.util.*;
    2. class Point{
    3. int x1, y1;
    4. int x2, y2;
    5. int color;
    6. Point(int x1, int y1, int x2, int y2, int color){
    7. this.x1 = x1;
    8. this.y1 = y1;
    9. this.x2 = x2;
    10. this.y2 = y2;
    11. this.color = color;
    12. }
    13. }
    14. public class Test{
    15. //拿起刷子的最少次数
    16. public static int ans = Integer.MAX_VALUE;
    17. //平板的个数
    18. public static int n;
    19. public static final int N = 16;
    20. //存储平板的左上角、右下角坐标,当前平板的yanse
    21. public static Point[] matrix = new Point[N+1];
    22. //存储当前平板涂色需要满足的前置平板个数
    23. //(即只有所有前置平板个数都被涂色后,当前平板才能进行涂色)
    24. public static int[] ind = new int[N+1];
    25. //存储当前平板的后续平板(类似图的邻接节点)
    26. public static int[][] G = new int[N+1][N+1];
    27. //当前平板的访问情况(防止重复访问)
    28. public static boolean[] visited = new boolean[N+1];
    29. //预处理出所有平板的前置平板个数和平板之间的访问顺序
    30. public static void init(){
    31. //预处理平板之间涂色先后顺序
    32. for (int i = 1; i <= n; i++){
    33. for (int j = 1; j <= n; j++){
    34. if(matrix[i].x2 == matrix[j].x1 && !(matrix[i].y1 > matrix[j].y2 || matrix[j].y1 > matrix[i].y2)){
    35. //代表平板i涂色后可以访问到平板j
    36. G[i][j] = 1;
    37. //代表平板j涂色需要满足平板i也涂色
    38. //并且可能存在多个前置平板涂色的情况
    39. ind[j]++;
    40. }
    41. }
    42. }
    43. }
    44. public static void dfs(int step, int color, int cnt){
    45. //step: 涂色的次数,最坏情况下,每次只能涂一个平板,最大值为n
    46. //color: 当前刷子的颜色
    47. //cnt: 当前拿起刷子的次数
    48. if(ans <= cnt) //剪枝
    49. return;
    50. if(step == n){ //更新最优结果
    51. ans = cnt;
    52. return;
    53. }
    54. for(int i = 1; i <= n; i++){
    55. if(!visited[i] && ind[i] == 0){ //没有访问过 并且 前置平板均已涂色
    56. visited[i] = true;
    57. for(int j = 1; j <= n; j++){
    58. if(G[i][j] == 1){
    59. ind[j]--;
    60. }
    61. }
    62. if(color == matrix[i].color){ //如果当前平板的颜色与刷子的颜色相同,则不用更换刷子
    63. dfs(step + 1, color, cnt);
    64. }else{ //否则需要更换刷子,拿起刷子的次数+1
    65. dfs(step + 1, matrix[i].color, cnt + 1);
    66. }
    67. //回溯
    68. for(int j = 1; j <= n; j++){
    69. if(G[i][j] == 1)
    70. ind[j]++;
    71. }
    72. visited[i] = false;
    73. }
    74. }
    75. }
    76. public static void main(String[] args) {
    77. Scanner sc = new Scanner(System.in);
    78. n = sc.nextInt();
    79. int x1, x2, y1, y2, color;
    80. for(int i = 1; i <= n; i++){
    81. x1 = sc.nextInt();
    82. y1 = sc.nextInt();
    83. x2 = sc.nextInt();
    84. y2 = sc.nextInt();
    85. color = sc.nextInt();
    86. matrix[i] = new Point(x1, y1, x2, y2, color);
    87. }
    88. //预处理
    89. init();
    90. //从左上角进行搜索
    91. //并且递归入口是没有使用刷子的
    92. dfs(0, 0, 0);
    93. System.out.println(ans);
    94. }
    95. }