区域坐标离散化

来源:互联网 发布:淘宝不交保证金 编辑:程序博客网 时间:2024/06/06 14:14

个人感想

经过了这次网络赛我知道了基础技巧的重要性,从挑战程序设计上一直在看常用技巧,包括尺取法,双向搜索等等。看了挑战程序设计的164页坐标离散化之后特写篇博文来终结一下。

算法分析

首先对于一个很大的区域但是障碍很少的情况下直接进行广搜是很不合理的,因此我们需要对区域坐标进行离散化缩小区域,然后进行广搜,这样会大大减少时间复杂度。很明显这个区域里面有n条直线,那么我们需要将这条直线上的2个端点进行离散化,但是这样不合理,因为不同的线与线之间还有间距,因此我们需要将端点的左右坐标或者是上下坐标进行存储存入vec中,因为vec里面有重复元素,因此需要去重,排序之后利用STL的unique方法即可。然后通过find函数计算出新的顶点左边,这样就完成离散化了,然后对于得到的区域进行bfs即可。(注意:挑战程序设计一书上面x与y坐标是反的,我看了半天!!坑!!)

#include <queue>#include <vector>#include <cstdio>#include <cstring>#include <iostream>#include <algorithm>using namespace std;const int maxn = 505;#define PII pair <int, int>int W, H, N;int x1[maxn], x2[maxn], y1[maxn], y2[maxn];int dir[4][2] = {{-1,0},{1,0},{0,-1},{0,1}};bool fld[maxn*6][maxn*6];int compress(int *x1, int *x2, int w){    vector <int> vec;    vec.clear();    for(int i = 0; i < N; i++){  //找到本次点坐标以及相邻点坐标        for(int d = -1; d <= 1; d++){            int xx = x1[i] + d, yy = x2[i] + d;            if(1 <= xx && xx <= w) vec.push_back(xx);            if(1 <= yy && yy <= w) vec.push_back(yy);         }    }    sort(vec.begin(), vec.end());  //排序    vec.erase(unique(vec.begin(), vec.end()), vec.end()); //去重    for(int i = 0; i < N; i++){  //计算新的坐标        x1[i] = find(vec.begin(), vec.end(), x1[i]) - vec.begin();        x2[i] = find(vec.begin(), vec.end(), x2[i]) - vec.begin();    }    return vec.size();}void solve(){    W = compress(x1, x2, W);  //离散化    H = compress(y1, y2, H);    memset(fld, 0, sizeof(fld));    for(int i = 0; i < N; i++)        for(int y = y1[i]; y <= y2[i]; y++)            for(int x = x1[i]; x <= x2[i]; x++)                fld[x][y] = true;    int ans = 0;  //bfs    for(int x = 0; x < W; x++){        for(int y = 0; y < H; y++){            if(fld[x][y]) continue;            ans++;            queue <PII> que;            que.push(make_pair(x, y));            while(!que.empty()){                PII cur = que.front(); que.pop();                for(int i = 0; i < 4; i++){                    int xx = dir[i][0] + cur.first, yy = cur.second + dir[i][1];                    if(xx < 0 || xx >= W || yy < 0 || yy >= H || fld[xx][yy]) continue;                    que.push(make_pair(xx, yy));                    fld[xx][yy] = true;                }            }        }    }    printf("%d\n", ans);}int main(){    #ifdef LOCAL_BUG        freopen("input.txt", "r", stdin);    #endif // LOCAL_BUG    while(scanf("%d%d%d", &W, &H, &N) != EOF){        for(int i = 0; i < N; i++) scanf("%d", &x1[i]);        for(int i = 0; i < N; i++) scanf("%d", &x2[i]);        for(int i = 0; i < N; i++) scanf("%d", &y1[i]);        for(int i = 0; i < N; i++) scanf("%d", &y2[i]);        solve();    }    return 0;}
0 0