hiho一下第234周《矩形计数》题目与解答

一、题目

题目1 : 矩形计数

时间限制:10000ms
单点时限:1000ms
内存限制:256MB

描述

如图所示,在由N行M列个单位正方形组成的矩形中,有K个单位正方形是黑色的,其余单位正方形是白色的。  

你能统计出一共有多少个不同的子矩形是完全由白色单位正方形组成的吗?

输入

第一行三个整数:N, M和K。

之后K行每行包括两个整数R和C,代表一个黑色单位正方形的位置。

1 <= N,M <= 1000  

1 <= K <= 10  

1 <= R <= N  

1 <= C <= M

输出

输出一个整数表示满足条件的子矩形个数。

样例输入
3 3 1
2 3 
样例输出
24


二、思路

一开始没有思路,参考了官方分析之后豁然开朗。问题的关键点在于想到容斥原理和题解中的这句话:
我们知道只要确定矩形上边界、下边界、左边界和右边界的位置,就唯一确定了一个矩形。

三、实现

dfs实现容斥原理可以考虑用二进制来表示选取的集合状态。

 1 //@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@A@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@
 2  #include <iostream>
 3  #include <cstring>
 4  #include <cstdio>
 5  #include <string>
 6  #include <queue>
 7  #include <list>
 8  #include <map>
 9  #include <set>
10  #include <cmath>
11  #include <bitset>
12  #include <vector>
13  #include <sstream>
14  #include <cstdlib>
15  #include <algorithm>
16  using namespace std;
17  typedef long long  ll;
18  #define mem(A, X) memset(A, X, sizeof A)
19  #define foreach(e,x) for(__typeof(x.begin()) e=x.begin();e!=x.end();++e)
20  #define fori(i,l,u) for(ll (i)=(ll)(l);(i)<=(ll)(u);++(i))
21  #define ford(i,l,u) for(ll (i)=(ll)(l);(i)>=(ll)(u);--(i)) 
22 ll n,m,k;
23 const int maxsz=1005;
24 ll pr[maxsz],pc[maxsz];
25 ll sum;
26 ll cal(ll s){
27   if (s==0) return (n*n+n)*(m*m+m)/4;
28   ll lc=1000,rc=0,ur=0,dr=1000;
29   int cnt=0;
30 
31   //cout<<"----- s is : "<<s;
32   fori(i,1,k){
33    if(s&1){
34      lc=min(lc,pc[i]-1);
35      rc=max(rc,pc[i]);
36      ur=max(ur,pr[i]);
37      dr=min(dr,pr[i]-1);
38    }
39    s=s>>1;
40   }
41   //cout<<"  lc rc ur dr"<<lc<<" "<<rc<<" "<<ur<<" "<<dr<<endl;
42   ll sumx=(lc+1)*(m-rc+1);
43   //if(lx==rx) sumx=n*lx-lx*rx+n-rx+lx;
44   ll sumy=(dr+1)*(n-ur+1);
45   //if(lx==rx) sumy=n*lx-lx*rx+n-rx+lx;
46 
47   return sumx*sumy;
48 }
49 void dfs(ll cnt,ll s){
50   if(cnt<k){
51     int ns=(s<<1)+0;
52     dfs(cnt+1,ns);
53     ns=(s<<1)+1;
54     dfs(cnt+1,ns);
55   }else{
56     int cnt1=0;
57     int ts=s;
58     int cnt=k;
59     while(cnt--) {
60       if(ts&1) cnt1++;
61       ts=ts>>1;
62     }
63     int sig=-1;
64     if((cnt1%2)==0) sig=1;
65     ll temp=cal(s);
66     sum+=sig*temp;
67   }
68 
69 }
70 
71 
72  int main()
73  {
74   ios::sync_with_stdio(false);
75   //freopen("local.in","r",stdin);
76   //freopen("local.out","w",stdout);
77 
78   while(cin>>n>>m>>k){
79     fori(i,1,k) cin>>pr[i]>>pc[i];
80     sum=0;
81     dfs(0,0);
82     cout<<sum<<endl;
83   }
84 
85   return 0;
86  }
87 
88 //
89 //
90 //@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@DEBUG@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@
View Code

 

 

posted @ 2018-12-26 21:38  TechIsOnlyTool  阅读(183)  评论(0编辑  收藏  举报