• 洛谷P1283 平板涂色题解


    本题是状态压缩的dp题目,具体注释在代码当中,有挺多细节

    #include<iostream>
    #include<string>
    #include<vector>
    #include<cstdio>
    #include<queue>
    #include<algorithm>
    #include<cstring>
    using namespace std;
    const int N=1<<16+1;
    const int M=21;
    const int inf=0x3f3f3f3f;
    int f[N][21];
    int up[M][M];
    int num[M];
    int col[M];
    int g[110][110]; 
    int x1[M],x2[M],y1[M],y2[M];
    int sign;
    bool check(int u,int x){ //检查是否满足上面都涂了条件 
        bool flag=true;
        for(int i=1;i<=num[x];i++)
            if(!((1<<(up[x][i]-1))&u)){
            flag=false;    
            break;
            }
            
        return flag;
    }
    int main(){
        int i;
        int j,k;
        int n;
        cin>>n;
        for(i=1;i<=n;i++){
            cin>>y1[i]>>x1[i]>>y2[i]>>x2[i]>>col[i];
            sign=max(sign,col[i]);
            for(j=y1[i];j<y2[i];j++){ //这里要注意不是j<=y2[i],因为假如有两个矩形的边重叠了的情况,我们默认只使用一边 
                for(k=x1[i];k<x2[i];k++)
                g[j][k]=i;
            }
        }
        for(i=1;i<=n;i++){  //将上方的情况枚举出来 
            if(!y1[i])
            continue;
            int u=y1[i]-1;
            for(j=x1[i];j<x2[i];){
                if(g[u][j]){
                int l=j;
                while(g[u][j]==g[u][l]&&l<x2[i])
                l++;
                up[i][++num[i]]=g[u][j];
                j=l;    
                }
            }
        }
        memset(f,40,sizeof f);
        for(i=1;i<=sign;i++)
        f[0][i]=1; //对于未涂色的情况,刚开始的任何一种颜色的次数都是1 
        for(i=1;i<=(1<<n)-1;i++){ //枚举所有涂色情况,这样就可以遍历所有状态 
            for(j=1;j<=n;j++){  //枚举涂每块的情况 
                if(((1<<(j-1))&i)==(1<<(j-1))&&check(i,j)){ //检查该位置是否已经涂上该颜色,只有涂上了才可以用其他状态转移他
                                                             //还需上面都涂过 
                    for(k=1;k<=sign;k++){  //枚举之前的是那种颜色 
                        if(k!=col[j]){  
                            f[i][col[j]]=min(f[i-(1<<(j-1))][k]+1,f[i][col[j]]);
                        }
                    }
                    f[i][col[j]]=min(f[i][col[j]],f[i-(1<<(j-1))][col[j]]);
                    
                }
            }
        }
        int ans=inf;
        for(i=1;i<=sign;i++){
            ans=min(ans,f[(1<<n)-1][i]);
            
        }
        cout<<ans<<endl;
    }
    View Code
  • 相关阅读:
    Javascript 使用字符串
    JavaScript精简学习4(动态表单和链接处理)
    JavaScript 使用表单
    事半功倍之Javascript (2)
    jQuery隐藏按钮
    .NET线程同步之Interlocked和ReadWrite 锁线程同步——事件构造
    linux命令汇总
    好的设计能减少大量的工作
    Prism学习笔记
    编写C函数的技巧
  • 原文地址:https://www.cnblogs.com/ctyakwf/p/12245931.html
Copyright © 2020-2023  润新知