[暑假集训Day3T3]平板涂色

同样是搜索经典题。

优化并不多,只需在当前步数已经大于目前答案时剪枝就可以了。

此题重点在于如何判断第k个矩形能不能选。

设矩形i的左上坐标为i(squ[i].upx,squ[i].upy),右下角坐标为i(squ[i].dox,squ[i].doy)。则判断k号矩形可以涂的条件为:

if(!vis[i]&&(squ[k].upy==squ[i].doy)&&((squ[i].upx>=squ[k].upx&&squ[i].upx<=squ[k].dox)||(squ[i].dox>=squ[k].upx&&squ[i].dox<=squ[k].dox)))

即:如果i号矩形没有涂色且i号矩形为紧靠k上方的矩形,就不可以涂色。

重点来解释一下如何判定i号矩形为紧靠k矩形上方的矩形。

第一,如果i号矩形为紧靠k矩形上方的矩形,那么i号矩形右下角的纵坐标一定等于k号矩形左上角的纵坐标,这个很好理解,对应判断条件中的(squ[k].upy==squ[i].doy)。

第二,如何判断[squ[i].upx,squ[i].dox]和[squ[k].upx,squ[i].dox]有没有交集呢?只需要看是否有一个端点位于线段中即可,读者可以结合下图理解:

[暑假集训Day3T3]平板涂色

下面正常深搜即可。

下面给出参考代码:

#include<iostream>
#include<cstdio>
#define N 205
using namespace std;
struct node
{
    int upx,upy,dox,doy,col;
}squ[N];
int n,ans;
bool vis[N];
bool check(int k)
{
    for(int i=1;i<=n;i++)
    {
        if(!vis[i]&&(squ[k].upy==squ[i].doy)&&((squ[i].upx>=squ[k].upx&&squ[i].upx<=squ[k].dox)||(squ[i].dox>=squ[k].upx&&squ[i].dox<=squ[k].dox)))return 0;
    }
    return 1;
}
void dfs(int step,int node,int col)
{
    if(step>=ans)return;
    if(node==n)ans=step;
    for(int i=1;i<=n;i++)
    {
        if(!vis[i]&&check(i))
        {
            if(squ[i].col==col)
            {
                vis[i]=1;
                dfs(step,node+1,col);
                vis[i]=0;
            }
            else 
            {
                vis[i]=1;
                dfs(step+1,node+1,squ[i].col);
                vis[i]=0;
            }
        }
    }
}
int main()
{
    cin>>n;
    ans=n;
    for(int i=1;i<=n;i++)
    {
        cin>>squ[i].upy>>squ[i].upx>>squ[i].doy>>squ[i].dox>>squ[i].col;
    }
    dfs(0,0,-1);
    cout<<ans<<endl;
}

  

上一篇:【pwnable.kr】flag


下一篇:OpenMetadata 0.6 版本发布了