CCF认证 201912-2 《回收站选址》

读题审题,总结要点

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;
}


欢迎留言评论提问

发布了174 篇原创文章 · 获赞 18 · 访问量 1万+

猜你喜欢

转载自blog.csdn.net/qq_41173604/article/details/104145571