1. 程式人生 > >HDU-2461 Rectangles 容斥

HDU-2461 Rectangles 容斥

題意:給出n個矩形的左下角和右上角座標,要求進行m次操作,每次對t個矩形進行塗色(給出這t個矩形的序號),要求計算出每次塗色時需要塗色的面積。(塗色可以覆蓋,即每次操作不受前面任何操作的影響)。

分析:因為n很小,所以明顯用容斥就可以解決。奇加偶減,算相交面積。

一直習慣用位寫容斥,但這個題n是20,迴圈過多,TLE了,然後看vj上有人先用位打了個表,也挺快的,不過沒看懂,還是換過來用dfs寫吧。

#include<bits/stdc++.h>

using namespace std;

struct rect{
    int x1,y1,x2,y2;
    rect(int x1,int y1,int x2,int y2):x1(x1),y1(y1),x2(x2),y2(y2){}
    rect(){}
    int area(){
        if(x1>=x2||y1>=y2){
            return 0;
        }
        return (x2-x1)*(y2-y1);
    }
    rect cross(const rect& r){
        rect t;
        t.x1=max(x1,r.x1);
        t.y1=max(y1,r.y1);
        t.x2=min(x2,r.x2);
        t.y2=min(y2,r.y2);
        return t;
    }
}r[25];

int cnt,ans;
vector<int> v;

void dfs(int i,rect tmp,int num){
    tmp=tmp.cross(r[v[i]]);
    int area=tmp.area();
    if(area==0) return ;
    if(num%2) ans+=area;
    else ans-=area;
    for(int j=i+1;j<cnt;j++){
        dfs(j,tmp,num+1);
    }
}

int main(){
    int n,m;
    int cs=1;
    while(scanf("%d%d",&n,&m)!=EOF&&(n||m)){
        for(int i=1;i<=n;i++){
            scanf("%d%d%d%d",&r[i].x1,&r[i].y1,&r[i].x2,&r[i].y2);
        }
        printf("Case %d:\n",cs++);
        int css=1;
        while(m--){
            scanf("%d",&cnt);
            v.clear();
            ans=0;
            for(int i=0;i<cnt;i++){
                int a;scanf("%d",&a);
                v.push_back(a);
            }
            for(int i=0;i<cnt;i++){
                dfs(i,r[v[i]],1);
            }
            printf("Query %d: %d\n",css++,ans);
        }
        puts("");
    }
    return 0;
}