读题审题,总结要点
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;
}