矩阵的并 容斥原理
题意 :给出了n个矩阵, (n<=20), 现在有m(m<=100000)个询问, 要问若干个矩阵的并是多少。
思路: 开始的时候一直认为这道题是用线段树做, 后来发现原来也可以用容斥原理做,原因是n比较小。 比较暴力,但是有剪枝的地方。 即无论如何都不会有面积出现就break。
k个矩阵的并 = 1个矩阵的面积和 - 2个面积交的和+3。。。。。
AC代码:
View Code
#include <cstdio> #include <cstring> #include <iostream> #include <string> using namespace std; struct { int x0, y0, x1, y1; } p[21]; int ans[1<<21], ask[1<<21], n, m; inline void in(int &a) { char ch; while(ch = getchar(), ch < '0' || ch > '9'); a = ch - '0'; while(ch = getchar(), ch >= '0' && ch <= '9') { a = a * 10 + ch - '0'; } return; } void init() { for(int i=0; i<n; i++) { in(p[i].x0); in(p[i].y0); in(p[i].x1); in(p[i].y1); } int t, x; memset(ans, 0, sizeof(ans)); for(int i=1; i<=m; i++) { in(t); ask[i] = 0; while(t--) { in(x); ask[i] |= 1<<(x-1); } } } void solve() { int x0, y0, x1, y1, tp; for(int i=1; i<(1<<n); i++) { x0 = 0, y0 = 0; x1 = 1000, y1 = 1000; bool flag = 1; tp = 0; for(int j=0; j<n; j++) { if((1<<j)&i) { tp++; x0 = max(x0,p[j].x0); y0 = max(y0,p[j].y0); x1 = min(x1,p[j].x1); y1 = min(y1,p[j].y1); if(x0 >= x1 || y0 >= y1) { flag = 0; break; } } } if(flag) { for(int j=1; j<=m; j++) { if( (ask[j]|i) == ask[j]) { if(tp%2) { ans[j] += (x1-x0)*(y1-y0); } else ans[j] -= (x1-x0)*(y1-y0); } } } } for(int i=1; i<=m; i++) { printf("Query %d: %d\n", i, ans[i]); } } int main() { int t = 0; while(scanf("%d%d", &n, &m) != EOF) { if(n == 0 && m == 0) break; t++; init(); printf("Case %d:\n", t); solve(); printf("\n"); } return 0; }


浙公网安备 33010602011771号