[暑假集训]Day4 T3 平板涂色

问题 C: 平板涂色

时间限制: 1 Sec  内存限制: 512 MB
题目描述
CE 数码公司开发了一种名为自动涂色机(APM)的产品。它能用预约的颜色给一块由不一样尺寸且互不覆盖的矩形构成的平板涂色。

为了涂色,APM 须要使用一组刷子。每一个刷子涂一种不一样的颜色。APM拿起一把蘸有颜色 C的刷子 。并给全部颜色为C且符合下面限制的矩形涂色。为了不颜料渗漏致使颜色混合,一个矩形只能在全部紧靠它上方的矩形涂色后,才能涂色。例如图中矩形 F 必须在 C 和 D 涂色后才能涂色。注意,每个矩形必须马上涂满,不能只涂一部分。
写一个程序求一个使 APM 拿起刷子次数最少的涂色方案。注意,若是一把刷子被拿起超过一次,则每一次都必须记入总数中。
输入
第一行为矩形的个数 N 。
下面有 N 行描述了 N 个矩形。每一个矩形有 5 个整数描述,左上角的 y 坐标和 x 坐标,右下角的 y 坐标和 x 坐标,以及预约颜色。
颜色号为 1 到 20 的整数。平板的左上角坐标老是 (0,0),坐标的范围是0…99。N小于16。
输出
输出一个整数,表示拿起刷子的最少次数。
样例输入
7
0 0 2 2 1
0 2 1 6 2
2 0 4 2 1
1 2 4 4 2
1 4 3 6 1
4 0 6 4 1
3 4 6 6 2
样例输出
       3
 
     思路:这道题一看上去就知道是搜索,但洛谷上好像有一堆dalao都是用dp过的。蒟蒻瑟瑟发抖。由于这题的数据实在太水,因此搜索是根本不用去考虑剪
 枝,只用在当前次数大于等于ans时返回就能够了。不过这道题里惟一的难点就是如何判断矩形的上下关系,这个点卡了我两天。
处理好以后,只需在dfs函数里枚举颜色就行了。
参考代码:
 1 #include<bits/stdc++.h>
 2 using namespace std;
 3 struct lhy
 4 {
 5     int x1,y1,x2,y2,color;//设一个结构体来储存每个矩形的信息 
 6 }a[20];
 7 int n,ans=999999,maxn_color,flag[20];
 8 bool f[20][20],color_check[25];
 9 bool check(int t)//判断该矩形是否可涂 
10 {
11     for(int i=1;i<=n;i++)
12     {
13         if(f[t][i]==1&&flag[i]==0) return false;
14     }
15     return true;
16 }
17 void dfs(int color_now,int s,int sum)//当前的颜色   步数   已图的块数 
18 {
19     if(s>=ans) return ;//惟一的剪枝 
20     if(sum==n) 
21     {
22         ans=s;
23         return ;
24     }
25     for(int i=1;i<=maxn_color;i++)//枚举颜色 
26     {
27         if(i!=color_now&&color_check[i]==1)
28         {
29             int glq=0;
30             for(int j=1;j<=n;j++)
31             {
32                 if(flag[j]==0&&a[j].color==i&&check(j)==true)
33                 {
34                     flag[j]=1;
35                     glq++;
36                 }
37                 else if(flag[j]>=1&&a[j].color==i) flag[j]++;
38             }
39             if(glq>0) dfs(i,s+1,sum+glq);
40             for(int j=n;j>=1;j--)//不要忘记回溯 
41             {
42                 if(flag[j]==1&&a[j].color==i&&check(j)==true)
43                 {
44                     flag[j]=0;
45                     glq--;
46                 }
47                 else if(flag[j]>1&&a[j].color==i) 
48                 {
49                     flag[j]--;
50                 }
51             }
52         }
53     }    
54 }
55 int main()
56 {
57     scanf("%d",&n);
58     for(int i=1;i<=n;i++)
59     {
60         scanf("%d%d%d%d%d",&a[i].x1,&a[i].y1,&a[i].x2,&a[i].y2,&a[i].color);
61         color_check[a[i].color]=1;
62         maxn_color=max(a[i].color,maxn_color);
63     }
64     for(int i=1;i<=n;i++)
65     {
66         for(int j=1;j<=n;j++)
67         {
68             if(i!=j&&f[j][i]==0)
69             {
70                 if(a[i].x1==a[j].x2&&a[i].y1<=a[j].y2&&a[i].y2>=a[j].y1) f[i][j]=1;//最重要的一点!!!!判断矩形的上下关系 
71             }
72         }
73     }
74     dfs(0,0,0);
75     printf("%d",ans);
76     return 0;
77 }
 
   
这题总的来讲并不难,但想要在考场上拿到满分仍是有必定难度的。但愿这篇题解能对正在考模拟赛的你产生些许帮助。

转载于:https://www.cnblogs.com/jiuduSHENBENG/p/11178426.htmlhtml