• P1283 平板涂色


    P1283 平板涂色

    dfs 记忆化搜索

    将矩阵转化为图求解,然后我们发现这是个DAG,于是就可以愉快地跑搜索了。

    进行dfs时,我们可以用类似拓扑排序的方法。每次将上面所有矩形都被刷过(入度in[ i ]==0)的满足条件的矩形用h数组打个标记

    用incol数组表示目前h数组中有几种颜色,然后枚举可转移状态进行dfs

    发现数据n<16,于是我们可以将状态用二进制存起来(0/1表示是否已被刷)进行记忆化搜索

    #include<iostream>
    #include<cstdio>
    #include<cstring>
    using namespace std;
    inline int _max(int &a,int &b) {return a>b ? a:b;}
    inline int _min(int &a,int &b) {return a<b ? a:b;}
    struct matr{int x1,y1,x2,y2;}a[18];
    bool d[18][18],h[18];
    int n,ans=1e9,color,in[18],col[18],incol[22],rec[65538]; //rec:存状态,用作记忆化
    inline void dfs(int t,int x,int zip){ //t:拿起刷子最少次数 x:已刷几个格子 zip:当前状态
        if(rec[zip]&&rec[zip]<=t) return ; //记忆化搜索
        else rec[zip]=t;
        if(x==n) {ans=_min(ans,t); return ;} //所有矩形已刷过
        int tmp1[18],tmp2[22],tmp3[18],cnt,p;
        for(int i=1;i<=n;++i) tmp1[i]=h[i],tmp3[i]=in[i];
           for(int i=1;i<=color;++i) tmp2[i]=incol[i]; //用tmp数组保存当前状态
        for(int i=1;i<=color;++i)
        {
            cnt=0; p=zip;
            if(!incol[i]) continue;
            while(incol[i]) //一直使用该种颜色直到无法再刷
            {
                for(int j=1;j<=n;++j)
                    if(h[j]&&col[j]==i){
                        --incol[i]; h[j]=0; ++cnt; p+=1<<j; //取出有标记的点
                        for(int u=1;u<=n;++u) //枚举下一层
                            if(d[j][u]){
                                --in[u];
                                if(in[u]==0) h[u]=1,++incol[col[u]]; //打上标记
                            }
                    }
            }
            dfs(t+1,x+cnt,p);
            for(int j=1;j<=n;++j) h[j]=tmp1[j],in[j]=tmp3[j];
            for(int j=1;j<=color;++j) incol[j]=tmp2[j]; //当前状态回溯
        }
    }
    int main(){
        scanf("%d",&n);
        for(int i=1;i<=n;++i){
            scanf("%d%d%d%d%d",&a[i].y1,&a[i].x1,&a[i].y2,&a[i].x2,&col[i]);
            color=_max(color,col[i]);
        }
        for(int i=1;i<=n;++i)
            for(int j=1;j<=n;++j)
                if(i!=j&&a[i].y2==a[j].y1&&a[i].x1<a[j].x2&&a[i].x2>a[j].x1)
                    d[i][j]=1,++in[j]; //建图
        for(int i=1;i<=n;++i) if(!in[i]) h[i]=1,++incol[col[i]];
        dfs(0,0,0);
        printf("%d",ans);
        return 0;
    }
  • 相关阅读:
    第六章 实验报告(函数与宏定义)
    第三次实验报告
    第五章 循环结构课后反思
    第二次实验报告
    第一次实验报告
    第一次作业
    第九章 结构体与共用体
    第八章 指针实验
    第7章 数组实验
    第六章 函数和宏定义实验(2)
  • 原文地址:https://www.cnblogs.com/kafuuchino/p/9581901.html
Copyright © 2020-2023  润新知