题目链接:https://www.dotcpp.com/oj/problem2356.html
import java.util.*;class Point{int x1, y1;int x2, y2;int color;Point(int x1, int y1, int x2, int y2, int color){this.x1 = x1;this.y1 = y1;this.x2 = x2;this.y2 = y2;this.color = color;}}public class Test{//拿起刷子的最少次数public static int ans = Integer.MAX_VALUE;//平板的个数public static int n;public static final int N = 16;//存储平板的左上角、右下角坐标,当前平板的yansepublic static Point[] matrix = new Point[N+1];//存储当前平板涂色需要满足的前置平板个数//(即只有所有前置平板个数都被涂色后,当前平板才能进行涂色)public static int[] ind = new int[N+1];//存储当前平板的后续平板(类似图的邻接节点)public static int[][] G = new int[N+1][N+1];//当前平板的访问情况(防止重复访问)public static boolean[] visited = new boolean[N+1];//预处理出所有平板的前置平板个数和平板之间的访问顺序public static void init(){//预处理平板之间涂色先后顺序for (int i = 1; i <= n; i++){for (int j = 1; j <= n; j++){if(matrix[i].x2 == matrix[j].x1 && !(matrix[i].y1 > matrix[j].y2 || matrix[j].y1 > matrix[i].y2)){//代表平板i涂色后可以访问到平板jG[i][j] = 1;//代表平板j涂色需要满足平板i也涂色//并且可能存在多个前置平板涂色的情况ind[j]++;}}}}public static void dfs(int step, int color, int cnt){//step: 涂色的次数,最坏情况下,每次只能涂一个平板,最大值为n//color: 当前刷子的颜色//cnt: 当前拿起刷子的次数if(ans <= cnt) //剪枝return;if(step == n){ //更新最优结果ans = cnt;return;}for(int i = 1; i <= n; i++){if(!visited[i] && ind[i] == 0){ //没有访问过 并且 前置平板均已涂色visited[i] = true;for(int j = 1; j <= n; j++){if(G[i][j] == 1){ind[j]--;}}if(color == matrix[i].color){ //如果当前平板的颜色与刷子的颜色相同,则不用更换刷子dfs(step + 1, color, cnt);}else{ //否则需要更换刷子,拿起刷子的次数+1dfs(step + 1, matrix[i].color, cnt + 1);}//回溯for(int j = 1; j <= n; j++){if(G[i][j] == 1)ind[j]++;}visited[i] = false;}}}public static void main(String[] args) {Scanner sc = new Scanner(System.in);n = sc.nextInt();int x1, x2, y1, y2, color;for(int i = 1; i <= n; i++){x1 = sc.nextInt();y1 = sc.nextInt();x2 = sc.nextInt();y2 = sc.nextInt();color = sc.nextInt();matrix[i] = new Point(x1, y1, x2, y2, color);}//预处理init();//从左上角进行搜索//并且递归入口是没有使用刷子的dfs(0, 0, 0);System.out.println(ans);}}
