【bzoj1709/Usaco2007 Oct】Super Paintball超级弹珠——递推

Description

奶牛们最近从著名的奶牛玩具制造商Tycow那里,买了一套仿真版彩弹游戏设备(类乎于真人版CS)。 Bessie把她们玩游戏草坪划成了N * N(1 <= N<= 100)单位的矩阵,同时列出了她的 K (1 <= K <= 100,000)个对手在草地上的位置。然后她拿着这张表来找你,希望你能帮她计算一个数据。 在这个游戏中,奶牛可以用一把弹珠枪向8个方向中的任意一个射出子弹。8个方向分别是:正北,正南,正东,正西,以及夹在这4个正方向之间的45°角:东北,东南,西北,西南方向。 Bessie望你告诉她,如果她想站在一个可以射到她的所有对手的格子上,那么她有多少种选择。当然,贝茜可以跟她的某一个对手站在同一个格子上,并且在这种情况下,你可以认为贝茜能射到跟她站在同一格子里的对手。

Input

* 第1行: 2个用空格隔开的整数:N和K

* 第2..K+1行: 第i+1行用2个以空格隔开整数R_i和C_i,描述了第i头奶牛的位置,表示她站在第R_i行,第C_i列

Output

* 第1行: 输出1个整数,表示如果Bessie可以选择的格子的数目。

Sample Input

4 3
2 1
2 3
4 1

输入说明:

牧场被划分成了4行4列。Bessie的站位必须保证她能射到站在(2,1),(2,3)

以及(4,1)的奶牛:

. . . .
C . C .
. . . . <--- 奶牛们的位置
C . . .

Sample Output

5
 

读入的时候就把这一行、列、上升对角线(左下->右上),下降对角线的值+1。
O(n2)枚举每个点,计算这个点行、列、对角线上值的总和,若值恰好为m,则ans++。
特别的,当枚举到的点本身就有敌人时,答案会把本身算4次,要减去3*mp[i][j]。
代码:
 1 #include<cstdio>
 2 #include<cstring>
 3 #include<queue>
 4 #include<cmath>
 5 const int N=200;
 6 int n,m,mp[N][N];
 7 int h[N],s[N],xi[N],yi[N];
 8 int read(){
 9     int ans=0,f=1;char c=getchar();
10     while(c<'0'||c>'9'){if(c=='-')f=-1;c=getchar();}
11     while(c>='0'&&c<='9'){ans=ans*10+c-48;c=getchar();}
12     return ans*f;
13 }
14 int main(){
15     n=read();m=read();
16     for(int i=1,a,b;i<=m;i++){
17         a=read();b=read();mp[a][b]++;
18         h[a]++;s[b]++;xi[n-(b-a)]++;yi[a+b-1]++;
19     }
20     int sum=0;
21     for(int i=1;i<=n;i++){
22         for(int j=1;j<=n;j++){
23             int num=h[i]+s[j]+xi[n-(j-i)]+yi[i+j-1];
24             if(mp[i][j])num-=mp[i][j]*3;
25             if(num==m)sum++;
26         }
27     }
28     printf("%d\n",sum);
29     return 0;
30 }
31 
bzoj1709

 

posted @ 2017-10-13 20:51  Child-Single  阅读(138)  评论(0编辑  收藏  举报