POJ1691 Painting A Board ACM解题报告(DFS+构造)难题=。=

来源:互联网 发布:dp网络 编辑:程序博客网 时间:2024/05/16 18:33


大致题意:

墙上有一面黑板,现划分为多个矩形,每个矩形都要涂上一种预设颜色C。

由于涂色时,颜料会向下流,为了避免处于下方的矩形的颜色与上方流下来的颜料发生混合,要求在对矩形i着色时,处于矩形i上方直接相邻位置的全部矩形都必须已填涂颜色。

在填涂颜色a时,若预设颜色为a的矩形均已着色,或暂时不符合着色要求,则更换新刷子,填涂颜色b。

 

注意:

1、  当对矩形i涂色后,发现矩形i下方的矩形j的预设颜色与矩形i一致,且矩形j上方的全部矩形均已涂色,那么j符合填涂条件,可以用 填涂i的刷子对j填涂,而不必更换新刷子。

2、  若颜色a在之前填涂过,后来填涂了颜色b,现在要重新填涂颜色a,还是要启用新刷子,不能使用之前用于填涂颜色a的刷子。

3、  若颜色a在刚才填涂过,现在要继续填涂颜色a,则无需更换新刷子。

4、  矩形着色不能只着色一部分,当确认对矩形i着色后,矩形i的整个区域将被着色。

 

首先要注意输入数据,每个矩形信息的输入顺序是 y x y x c,而不是 x y x y c

若弄反了x y坐标怎样也不会AC的.....

这题主要思路就是把长方形看成点,然后判断上下的长方形是否连通,即上面的长方形的ry=下方的长方形的ly,并且不能错开,得有相连部分,用数组记录他们的连通情况,并且记录每个点的入度。DFS回溯解决。

#include<iostream>#include<cstdio>#include<cstring>#include<algorithm>using namespace std;struct rect{    int lx,ly,rx,ry,col;}r[16];int n,ans,deg[16];//每个长方形的入度,当他上面与几块长方形连接时,就有多少入度,如果上面一块被涂色了,就入度-1,入度为0是就是待涂色int m[16][16];//表明两个长方形之间的连通情况int vis[16];//长方形是否着色void build(){    for(int i=0;i<n;i++)    {        for(int j=0;j<n;j++)        {            if(r[i].ry==r[j].ly&&!(r[i].lx>=r[j].rx||r[i].rx<=r[j].lx))            {                m[i][j]=1;                deg[j]++;            }        }    }}void dfs(int dep,int cnt,int color){    if(cnt>=ans) return;//当前情况大于等于最优解,剪枝pass    if(dep==n)    {        ans=cnt;//前面已经pass掉了cnt大于等于ans的情况        return;    }    for(int i=0;i<n;i++)    {        if(!deg[i]&&!vis[i])        {            vis[i]=1;            for(int j=0;j<n;j++)            {                if(m[i][j]) deg[j]--;            }            if(r[i].col==color) dfs(dep+1,cnt,color);            else dfs(dep+1,cnt+1,r[i].col);//判断完颜色后决定是否换刷子            for(int j=0;j<n;j++)//回溯到上一个结点。进入下一种情况            {                if(m[i][j]) deg[j]++;            }            vis[i]=0;        }    }}int main(){    int t;    scanf("%d",&t);    while(t--)    {        scanf("%d",&n);        for(int i=0;i<n;i++)        {            scanf("%d %d %d %d %d",&r[i].ly,&r[i].lx,&r[i].ry,&r[i].rx,&r[i].col);        }        ans=20;        memset(m,0,sizeof(m));        memset(deg,0,sizeof(deg));        memset(vis,0,sizeof(vis));        build();        dfs(0,0,0);//第一次拿起刷子也算一次pick-up,所以都从0开始;        printf("%d\n",ans);    }    return 0;}

0 0