1709: [Usaco2007 Oct]Super Paintball超級彈珠
Time Limit: 5 Sec Memory Limit: 64 MBSubmit: 342 Solved: 266
[Submit][Status][Discuss]
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
2 1
2 3
4 1
輸入說明:
牧場被劃分成了4行4列。Bessie的站位必須保證她能射到站在(2,1),(2,3)
以及(4,1)的奶牛:
. . . .
C . C .
. . . . <--- 奶牛們的位置
C . . .
Sample Output
輸出說明:
Bessie可以選擇站在以下格子中的任意一個:(2,1),(2,3),(3,2),(4,1),
以及(4,3)。下右圖中,Bessie與其他牛共同佔有的格子被標記爲'*':
. . . . . . . .
B . B . ---\ * . * .
. B . . ---/ . B . .
B . B . * . B .
這題思維挺巧妙的,採取了逆向覆蓋的思維,計算每個位置被覆蓋的次數,而不是正向去枚舉每個點,覆蓋了多少點。其中主對角線用x-y+n表示,+n是爲了防止出現負數,副對角線用x+y表示,可以證明任意在同一條主對角線的格子的座標滿足x-y+n相等,同理任何在副對角線的格子滿足x+y相等,因此可以利用這個來確定某個格子是否被對角線的其他格子覆蓋,這裏還有一個問題,就是最後枚舉每個格子時,若該格子本來就有一個牛,那麼覆蓋應爲k-1,而該格子沒有牛時,覆蓋應爲k,這樣分兩種情況討論也可以,這裏加一點優化,對pos[x][y]加1,這樣在原先式子上減去3倍的pos[x][y],那麼未覆蓋時,pos=0,因此相當於沒減,就是被其他k個覆蓋,若本身覆蓋,則pos=1,此時相當於減3,被自身覆蓋+4,被其餘k-1覆蓋,+(k-1),最終4+(k-1)-3也剛好爲k,真是太巧妙了!
代碼:
#include<cstdio>
#include<iostream>
#include<cstring>
using namespace std;
int r[110],c[110],a[210],b[210];
int pos[110][110];
int ans;
int main()
{
int n,k,x,y;
scanf("%d%d",&n,&k);
for(int i=0;i<k;i++){
scanf("%d%d",&x,&y);
r[x]++,c[y]++,a[x+y]++,b[x-y+n]++;
pos[x][y]++;
}
for(int i=1;i<=n;i++)
for(int j=1;j<=n;j++)
if(r[i]+c[j]+a[i+j]+b[i-j+n]-3*pos[i][j]==k)
ans++;
printf("%d\n",ans);
return 0;
}