POJ--3695(容斥原理)
2015-05-16 01:29:10
题目:最多15个矩形,每次挑选一定数量的矩形进行覆盖,问总面积。
思路:容斥水题,1个矩形的面积 - 2个矩形面积的交 + 3个矩形面积的交 .... ,处理一下矩形两个点的坐标的变换即可。
#include <cstdio> #include <cstring> #include <cstdlib> #include <cmath> #include <vector> #include <map> #include <set> #include <stack> #include <queue> #include <string> #include <iostream> #include <algorithm> using namespace std; #define getmid(l,r) ((l) + ((r) - (l)) / 2) #define MP(a,b) make_pair(a,b) #define PB(a) push_back(a) typedef long long ll; typedef pair<int,int> pii; const double eps = 1e-8; const int INF = (1 << 30) - 1; int N,M,l[30],R; ll ans; struct Rec{ int a1,b1,a2,b2; }r[30]; void Dfs(int p,int cnt,int a1,int b1,int a2,int b2){ if(a1 > a2 || b1 > b2) return; if(p > R){ if(cnt == 0) return; int area = (a2 - a1) * (b2 - b1); //printf("cnt : %d , %d %d %d %d\n",cnt,a1,b1,a2,b2); if(cnt & 1) ans += area; else ans -= area; return; } int id = l[p]; Dfs(p + 1,cnt,a1,b1,a2,b2); Dfs(p + 1,cnt + 1,max(a1,r[id].a1),max(b1,r[id].b1), min(a2,r[id].a2),min(b2,r[id].b2)); } int main(){ int tt = 0; while(scanf("%d%d",&N,&M) != EOF,N + M){ for(int i = 1; i <= N; ++i) scanf("%d%d%d%d",&r[i].a1,&r[i].b1,&r[i].a2,&r[i].b2); printf("Case %d:\n",++tt); for(int i = 1; i <= M; ++i){ scanf("%d",&R); for(int j = 1; j <= R; ++j) scanf("%d",&l[j]); ans = 0; Dfs(1,0,0,0,1000,1000); printf("Query %d: %lld\n",i,ans); } puts(""); } return 0; }