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


歡迎留言評論提問

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章