讀題審題,總結要點
1、不可用數組存儲,座標點的範圍太大;
極限座標109,並且還可以是負數。
2、總結題目要點,解題算法
1、位置curr處一定有垃圾 → 遍歷所有給定的位置,n個,最多爲103
2、4個必須位置,上下左右,如果有存在一個位置沒有垃圾,這個點跳過
3、得分位置,四個對角位置,需要統計
(如何統計?遍歷curr周圍的位置。周圍如何體現,對座標排序)。
3、具體設計算法,計算算法可行性(時間複雜度,極端情況)
看以下圖
每個點要想成爲得分點,左邊和右邊至少各兩個點;
假如當前搜尋點爲(1,1),排序之後,他的前一個點一定是(1,0),後一個點一定是(1,1),題目已經說明不存在兩個相同的點
如何確定搜索邊界?
(1)座標點索引的範圍在[1,n-1]
(2)往左邊搜索,邊界爲(x-1,y-1),往右邊搜索邊界爲(x+1,y+1)
滿分cpp代碼,代碼中包含註釋
#include <cstdio>
#include <algorithm>
using namespace std;
const int maxn = 1005;
struct Pos{
int x;
int y;
};
int ans[5]={0}; //存儲結果
Pos pos[maxn];
int n;
bool cmp(Pos a,Pos b)
//如果熟悉的話可以使用 pair<int,int>,可以直接比較
{
if(a.x==b.x)
return a.y < b.y;
else
return a.x < b.x;
}
int lookFor(int curr)
// 線性搜索,複雜度是O(n)
{
//當前的位置是curr
int x = pos[curr].x;
int y = pos[curr].y;
int necessary=0; //必要條件
int score=0; //加分條件
// 往左邊搜索
int i = curr-1;
if(pos[i].x==x && pos[i].y==y-1)
{
necessary++;
i++;
}
else
return -1;
while(i>=0 &&
( pos[i].x==x || (pos[i].x==x-1 && pos[i].y >= y-1) ) )
{
if(pos[i].x==x-1)
{
if(pos[i].y==y) //必要條件
necessary++;
else if(pos[i].y==y+1 || pos[i].y==y-1) //加分條件
score++;
}
i--;
}
// 增加一個判斷,如果不等於2,就不用進行右邊的搜索
if(necessary!=2)
return -1;
// 往右邊搜索
i = curr+1;
if(pos[i].x==x && pos[i].y==y+1)
{
necessary++;
i++;
}
else
return -1;
while(i < n &&
( pos[i].x==x || (pos[i].x==x+1 && pos[i].y<=y+1) ) )
{
if(pos[i].x == x+1)
{
if(pos[i].y == y)
necessary++;
else if(pos[i].y == y-1 || pos[i].y == y+1)
score++;
}
i++;
}
if(necessary == 4)
return score;
else
return -1;
}
int main() {
scanf("%d",&n);
for(int i=0;i<n;i++) //輸入n個座標點
{
scanf("%d %d",&pos[i].x,&pos[i].y);
}
//根據座標排序,事件複雜度O(nlogn)
sort(pos,pos+n,cmp);
for(int i=2;i<n-2;i++) //循環n個
{
int score = lookFor(i); //複雜度O(n)
if(score == -1)
continue;
else
ans[score]++;
}
// 總的事件複雜度是O(nlogn +) + O(n^2) = O(n^2)
// n的規模是10^3,最大計算是10^6量級,可解。
for(int i=0;i<5;i++)
printf("%d\n",ans[i]);
return 0;
}