zoukankan      html  css  js  c++  java
  • CF1198E Rectangle Painting 2

    题目

    There is a square grid of size (n×n). Some cells are colored in black, all others are colored in white. In one operation you can select some rectangle and color all its cells in white. It costs (min(h,w)) to color a rectangle of size (h×w). You are to make all cells white for minimum total cost.

    The square is large, so we give it to you in a compressed way. The set of black cells is the union of (m) rectangles.

    大意是给你一个矩形,其中有一些点是黑色的,要你把它染成白色,每次可以选择一个矩形染色,染色的代价是矩形长和宽中较小的那个,问最小代价。

    思路

    网络流。。。

    主要是要把思路打开。

    对于一个染色矩形来说,如果一边的代价确定了,另一边尽量往大了取就是了。
    所以实际上是一次染几行,或几列。

    那么就要求,每一个黑色块至少被以行的形式覆盖或者以列的形式覆盖。

    这就构成了一个网络流的模型。

    我们将源点与每行连接,边权为行的代价,将每列和汇点连接,边权为列的代价,如果某一行和某一列的交界处为黑色,那么就将这一行和这一列连一条边权为oo的边,然后跑一次最小割就是最终答案了。

    代码

    #include<bits/stdc++.h>
    #define M 405
    using namespace std;
    const int inf=1e9;
    int n,m,s,t,h[M],tt=1;
    struct node{int x1,y1,x2,y2;}A[M];
    bool eg[M][M];
    int B1[M*M],b1,B2[M*M],b2;
    struct edge{int nxt,to,co;}G[M*M];
    void Add(int a,int b,int c){
        if(eg[a][b])return;
        G[++tt]=(edge){h[a],b,c};
        h[a]=tt;
        eg[a][b]=1;
    }
    int dep[M],cur[M];
    queue<int>Q;
    bool bfs(){
        memset(dep,-1,sizeof(dep));
        for(int i=s;i<=t;i++)cur[i]=h[i];
        while(!Q.empty())Q.pop();
        Q.push(s);dep[s]=0;
        while(!Q.empty()){
            int x=Q.front();Q.pop();
            for(int i=h[x];i;i=G[i].nxt){
                int u=G[i].to,c=G[i].co;
                if(dep[u]!=-1||!c)continue;
                dep[u]=dep[x]+1;
                if(u==t)return 1;
                Q.push(u);
            }
        }
        return 0;
    }
    int dfs(int x,int mi){
        if(x==t||!mi)return mi;
        int rlow=0,used=0;
        for(int& i=cur[x];i;i=G[i].nxt){
            int u=G[i].to,c=G[i].co;
            if(dep[u]!=dep[x]+1||!c)continue;
            if(rlow=dfs(u,min(c,mi-used))){
                used+=rlow;
                G[i].co-=rlow;
                G[i^1].co+=rlow;
                if(used==mi)break;
            }
        }
        return used;
    }
    int ans=0;
    void Dinic(){
        while(bfs())ans+=dfs(s,inf);
    }
    int main(){
        scanf("%d%d",&n,&m);
        for(int i=1;i<=m;i++){
            scanf("%d%d%d%d",&A[i].x1,&A[i].y1,&A[i].x2,&A[i].y2);
            B1[++b1]=A[i].x1;B1[++b1]=++A[i].x2;
            B2[++b2]=A[i].y1;B2[++b2]=++A[i].y2;
        }
        B1[++b1]=B2[++b2]=n+1;
        sort(B1+1,B1+b1+1);sort(B2+1,B2+b2+1);
        b1=unique(B1+1,B1+b1+1)-B1-1;
        b2=unique(B2+1,B2+b2+1)-B2-1;
        s=0,t=b1+b2+1;
        for(int i=1;i<=m;i++){
            A[i].x1=lower_bound(B1+1,B1+b1+1,A[i].x1)-B1;
            A[i].x2=lower_bound(B1+1,B1+b1+1,A[i].x2)-B1;
            A[i].y1=lower_bound(B2+1,B2+b2+1,A[i].y1)-B2;
            A[i].y2=lower_bound(B2+1,B2+b2+1,A[i].y2)-B2;
            for(int x=A[i].x1;x<A[i].x2;x++)
                for(int y=A[i].y1;y<A[i].y2;y++)
                    Add(x,y+b1,inf),Add(y+b1,x,0);
        }
        for(int i=1;i<b1;i++){Add(s,i,B1[i+1]-B1[i]);Add(i,s,0);}
        for(int i=1;i<b2;i++){Add(i+b1,t,B2[i+1]-B2[i]);Add(t,i+b1,0);}
        Dinic();printf("%d
    ",ans);
        return 0;
    }
    
  • 相关阅读:
    大数据学习相关知识点
    SSMS登记密码清除
    ubuntu 18.04下安装Hadoop
    ubuntu 常见命令整理
    ubuntu 18.04下安装Java
    JQuery ajax请求返回(parsererror)异常处理
    (转载) C/C++编译和链接过程详解 (重定向表,导出符号表,未解决符号表)
    编译器的原理
    笔试题积累
    构造函数为什么不能声明为虚函数
  • 原文地址:https://www.cnblogs.com/zryabc/p/11331988.html
Copyright © 2011-2022 走看看