#10023. 「一本通 1.3 练习 2」平板涂色

【题目描述】

原题来自:ICPC Tehran 1999

CE 数码公司开发了一种名为自动涂色机(APM)的产品。它能用预定的颜色给一块由不同尺寸且互不覆盖的矩形构成的平板涂色。

为了涂色,APM 需要使用一组刷子。每个刷子蘸了颜色 C 。APM 拿起一把蘸有颜色 C 的刷子,并给所有颜色为 C 的矩形涂色。请注意,涂色有顺序要求:为了避免颜料渗漏使颜色混合,一个矩形只能在所有紧靠它上方的矩形涂色后,才能涂色。例如图中矩形 FF 必须在 C 和 D 涂色后才能涂色。注意,每一个矩形必须立刻涂满,不能只涂一部分。

写一个程序求一个使 APM 拿起刷子次数最少的涂色方案。注意,如果一把刷子被拿起超过一次,则每一次都必须记入总数中。

【输入格式】

第一行为矩形的个数 N 。
下面有 NN 行描述了 N 个矩形。每个矩形有 5 个整数描述,左上角的 y 坐标和 x 坐标,右下角的 y 坐标和 x 坐标,以及预定颜色。

【输出格式】

一行一个整数,表示拿起刷子的最少次数。

【样例输入】

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

【数据范围与提示】

对于全部数据,1≤N≤14,颜色号为 1 到 20 的整数。保证平板的左上角坐标总是 (0, 0),坐标的范围是 0 到 9 。

时隔多年,我终于可以回到我亲切的CSDN了,开心的一批。最近几天都在比赛(考试),(其实今天也在考试,但是因为题目不是难到那种境界,所以我在重做之后有时间来写我等了好久的博客)

然后回到题目,我相信这道题一定折腾了不少人,没错我也搞了好久好久好久,但是看完这篇博客之后你就会感到身心愉悦,因为其实好像没有想象中那么难,但是初初拿到这道题还是会大吃一惊的。

 好了不说客套话了,回到题目,我们一如既往先分析题目引导思路啊。

#10023. 「一本通 1.3 练习 2」平板涂色_第1张图片

  • 我们就围绕这张图展开来讲
  • 首先,看到我圈出来的坐标了吗?很好,说明我们这道题要定义结构体,为什么呢?我之前提到过就是说大多数情况下,如果一道题提到了说要让你用坐标来表示,那么这道题多数都是用结构体,因为结构体在通过你的坐标排序之后,它是完整的,但是如果你是数组直接排序之后,你彼此的坐标可能是对不上的,这一点就很不好了,所以我们遇到坐标系,或者说遇到组队的东西的话,用结构体

 

  • 这些最基本的东西要处理好,然后就是第二步,深刻审题
  • 其实最开始我是没有说往搜索这方面想的,我反而觉得就是说这种求极值的东西,可能很大情况下都是用dp,我也想过用dp,就是把这整个储存下来,然后通过状态的转移就是通过我们刷子的定位也就是选择涂色的区域来折腾,但是我发现这个不太切合实
1.首先我们如果是这样的话,那么我们的定位变大了之后,你怎么去确定?
2.我们储存的是一个坐标方阵,光从内存上来看,这就已经够呛了
3.就是说我们的定位确实是我们可以来取舍的一个因素,但是你的这个因素你要怎么样简洁方便的去搞呢?
  • 所以想过这些之后,我就放弃了dp,既然是自己做题,肯定不会想着暴力,肯定是尽可能的想正解的对吧。所以看到这种方阵的鬼题之后,我想到了另外一道方阵鬼题之后 ,简单数迷,没错就是这道题,所以所以我就觉得这道题啊还是用搜索递归来折腾吧
  • 那么我们确定了目标之后,就是核心的搜索dfs的定义了,我们定义什么样的东西,决定了我们这道题是否成功,其实我觉得深搜最难的就是说:我们要怎么定义这个我们搜索的目的 
1.如果我们要搞的话,我们要从题目的主旨来分析,
这是我被深搜搞了这么久之后总结出来的
2.所以这道题我们要求的是次数,那么我们在dfs当中定义的时候,
就一定少不了int x表示次数,这个思路是可以理解的吧,所以很多人做题的时候,
特别是做搜索的时候,可以尝试着往这边想
3.然后因为题目涉及到了一个问题:就是说我们要涂色,而且我们要判断到底能不能涂色,
这就说,我们需要 int jilu(记录)来记录我们之前涂过颜色的砖块
4.还有就是题目有一个很关键的东西就是说,我们不是随随便便的涂,
我们是要涂啊涂,一直涂到我们涂完所有的砖块为止,
所以就有了 int sum来记录我们当前涂过的砖块的块数
  • 这些基本功都理解清楚之后,你们可以继续往下看了
  • 我刚刚提到了就是说我们的涂色的顺序是从上往下的,所以我们就涉及到了就是说我们的涂色是从上往下的,也就是说如果两块平板叠在一起的时候,就是说我们要搞出一种就是特别的情况就是说:重叠的情况,这是我们要重点折腾的,也就是说我们的东西就是说要有一个初始化,什么意思呢?简单来讲就是我们要把重叠的部分直接定义为已读。 

第一种情况第一步

#10023. 「一本通 1.3 练习 2」平板涂色_第2张图片

第一种情况第二步

#10023. 「一本通 1.3 练习 2」平板涂色_第3张图片

第一种情况解释

#10023. 「一本通 1.3 练习 2」平板涂色_第4张图片

第二种情况第一步

#10023. 「一本通 1.3 练习 2」平板涂色_第5张图片

第二种情况第二步

#10023. 「一本通 1.3 练习 2」平板涂色_第6张图片

第二种情况解释

#10023. 「一本通 1.3 练习 2」平板涂色_第7张图片

  • 很好!认真看好这几张图,这是关键,因为说我们要搞懂这个初始化很重要
  • 然后其实我们搞好了之后,大概我要说的也就差不多了,最后讲一下一个小重点,就是那个时间上面的优化:排序!!!简单明了,现在不多讲,下次专门写一篇博客来介绍那么优化啊

最后看代码吧!!!

#include
#include
#include
using namespace std;
struct node
{
    int x1,x2,y1,y2,c;/*x1 y1记录的是当前砖块左上角的坐标  x2 y2记录的是当前砖块右下角的坐标 c是颜色*/ 
}a[111000];
int xx[11000]={0};//记录当前这一块砖有没有被涂过,初始化没涂过,0表示没涂过,1表示涂过 
int b[110][110],n,m,ans=999;//ans初始化是最大的 
//b[i][j]记录的是第i块砖所在的位置是第j个,并且确定当前这个位置是否涂过颜色 
int yy[11000];//表示颜色的数量 
int cmp(node n1,node n2)//排序
{
    if(n1.y1!=n2.y1) return n1.y1=ans)//如果当前的值大于你要找的值,就退出不用找了 
    {
        return;
    }
    if(sum==n)//如果涂完了所有的砖块 
    {
        ans=x;//ans就是我们当前走过的步数 
        return;//返回到最终结果,也就是主函数那里 
    }
    for(int i=0;i0)//如果已经涂过了 
            {
                dfs(x+1,i,sum+h);//搜索下一块砖 
            }
            for(int j=n-1;j>=0;j--)//回溯,也就是发现本质上不能涂色的 
            {
                if(xx[j]==1&&a[j].c==i&&find(j))//涂过了,存在于所有的颜色当中,并且在找的时候上面涂过了 
                {
                    xx[j]=0;//当这块砖没涂过 
                    h--;//涂过的砖减1 
                }
                else if(xx[j]>1&&a[j].c==i)//如果他需要的颜色不存在,但是有存在在这里 
                {
                    xx[j]--;//减掉 
                }
            }
        }
    }
}
int main()
{
    scanf("%d",&n);
    for(int i=0;i=0;j--)
        {
            if(a[i].x1==a[j].y1&&((a[i].x2>=a[j].x2&&a[i].x2<=a[j].y2)
			                   || (a[i].y2>=a[j].x2&&a[i].y2<=a[j].y2)))
            {
                b[i][j]=1;//记录下当前的这i块砖的j个位置是涂过颜色的 
				
			/*如果i块的最上面,且紧邻j块最下面,
			并且两砖横坐标有重叠部分,即i块为j块,紧邻的那块砖*/ 
			
			/* 其实通过图我们不能看出就是说我们的图是会有重叠部分的*/
			
	/*其实我们判断这个是有目的的,因为题目中说了我们只有在涂完所有与它紧密
	相连的颜色之后,才能涂下面的*/		
            }
        }
    }
    dfs(0,0,0);//全部从0开始 
    printf("%d\n",ans);//输出答案 
    return 0;
}

 ok,这道题还是很经典的搜索,一定要好好收藏起来啊!!!

你可能感兴趣的:(LOJ)