codeforces 1198E Rectangle Painting 2 最小点覆盖

Posted mountaink

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了codeforces 1198E Rectangle Painting 2 最小点覆盖相关的知识,希望对你有一定的参考价值。

题目传送门

题意:

  有一个$n∗n$的网格,网格中有一些矩形是黑的,其他点都是白的。

  你每次可以花费$ min (h,w)$的代价把一个$h*w$的矩形区域变白。求把所有黑格变白的最小代价。

思路:

  对于一列来说,如果我们要把这一列涂白,那必定会一涂到底,这样对结果只会有好处。行也是这样。

  明白了这个之后,这道题就变成了一道需要离散化的最小点覆盖问题,离散化时注意这个是网格,所以$x2,y2$都需要加1处理,然后跑一边网络流即可。

#pragma GCC optimize (2)
#pragma G++ optimize (2)
#pragma comment(linker, "/STACK:102400000,102400000")
#include<bits/stdc++.h>
#include<unordered_map>
#define rep(i,a,b) for(int i=a;i<=b;++i)
#define dep(i,b,a) for(int i=b;i>=a;--i)
#define clr(a,b) memset(a,b,sizeof(a))
#define pb push_back
#define pii pair<int,int >
using namespace std;
typedef long long ll;
ll rd()

    ll x=0,f=1;char ch=getchar();
    while(ch<0||ch>9)if(ch==-)f=-1;ch=getchar();
    while(ch>=0&&ch<=9)x=x*10+ch-0;ch=getchar();
    return x*f;

const int inf=0x3f;
const int maxn=8e5+10;
const ll INFLL = 0x3f3f3f3f3f3f3f3f;
const int INF = 0x3f3f3f3f;

struct Edge 
    int to, flow, nxt;
    Edge()
    Edge(int to, int nxt, int flow):to(to),nxt(nxt), flow(flow)
edge[maxn << 2];

int head[maxn], dep[maxn];
int S, T;
int N, n, m, tot;

void Init(int n)

    N = n;
    for (int i = 0; i <= N; ++i) head[i] = -1;
    tot = 0;


void addv(int u, int v, int w, int rw = 0)

    edge[tot] = Edge(v, head[u], w); head[u] = tot++;
    edge[tot] = Edge(u, head[v], rw); head[v] = tot++;


bool BFS()

    for (int i = 0; i <= N; ++i) dep[i] = -1;
    queue<int>q;
    q.push(S);
    dep[S] = 1;
    while (!q.empty())
    
        int u = q.front();
        q.pop();
        for (int i = head[u]; ~i; i = edge[i].nxt)
        
            if (edge[i].flow && dep[edge[i].to] == -1)
            
                dep[edge[i].to] = dep[u] + 1;
                q.push(edge[i].to);
            
        
    
    return dep[T] < 0 ? 0 : 1;


int DFS(int u, int f)

    if (u == T || f == 0) return f;
    int w, used = 0;
    for (int i = head[u]; ~i; i = edge[i].nxt)
    
        if (edge[i].flow && dep[edge[i].to] == dep[u] + 1)
        
            w = DFS(edge[i].to, min(f - used, edge[i].flow));
            edge[i].flow -= w;
            edge[i ^ 1].flow += w;
            used += w;
            if (used == f) return f;
        
    
    if (!used) dep[u] = -1;
    return used;


int Dicnic()

    int ans = 0;
    while (BFS())
    
        ans += DFS(S, INF);
    
    return ans;

vector<int >vx,vy;
struct node
    int x1,y1,x2,y2;
a[60];
int main()

    while (~scanf("%d %d", &n, &m))
    
        rep(i,1,m)
            scanf("%d%d%d%d",&a[i].x1,&a[i].y1,&a[i].x2,&a[i].y2);
            a[i].x2++,a[i].y2++;
            vx.pb(a[i].x1),vx.pb(a[i].x2);
            vy.pb(a[i].y1),vy.pb(a[i].y2);
        
        sort(vx.begin(),vx.end());
        vx.erase(unique(vx.begin(),vx.end()),vx.end());
        sort(vy.begin(),vy.end());
        vy.erase(unique(vy.begin(),vy.end()),vy.end());
        int tx=vx.size(),ty=vy.size();
        S = 0, T = tx * ty+1;
        Init(T);
        for(int i=0;i<tx-1;i++)
            addv(S,i+1,vx[i+1]-vx[i]);
        
        for(int i=0;i<ty-1;i++)
            addv(tx+i+1,T,vy[i+1]-vy[i]);
        
        for(int i=0;i<tx-1;i++)
            for(int j=0;j<ty-1;j++)
                rep(k,1,m)
                    if(a[k].x1<=vx[i]&&a[k].x2>=vx[i+1]&&a[k].y1<=vy[j]&&a[k].y2>=vy[j+1])
                        addv(i+1,tx+j+1,INF);
                    
                
            
        
//        printf("debug\n");
        int ans = Dicnic();
        printf("%d\n", ans);
    

 

以上是关于codeforces 1198E Rectangle Painting 2 最小点覆盖的主要内容,如果未能解决你的问题,请参考以下文章

CF1198E Rectangle Painting 2(最小割 思维

CAD绘制矩形框命令

类与对象

Java实现网页截屏

事件处理

事件处理