无忧无虑
隔壁村李小花垂涎我已久,可是我是要做海贼王的男人,于是拒绝了李小花……

k近邻算法C++二维实现

这是一个k近邻算法的二维实现(即K=2的情况)。

#include <cstdio>
#include <cstring>
#include <iostream>
#include <algorithm>
#include <vector>
#include <queue>
#include <cmath>
using namespace std;
const double inf = 1000.0;
const int maxn = 10010;

void debug_dfs(int);
void go_method();
bool should_go(int);
void dfs(int);
void back_method();

double Left[maxn], Right[maxn], Top[maxn], Button[maxn];
int tree[maxn][2], parent[maxn], cnt = 0, n;
int depth[maxn];
struct point {
    double x, y;
};
vector<point> points[maxn];
queue<int> q;
point tmp[maxn];
point node[maxn];
point p0, anspoint;
int ansid;
double R;
bool cmpx(point a, point b) {
    return a.x < b.x;
}
bool cmpy(point a, point b) {
    return a.y < b.y;
}
int main() {
    scanf("%d", &n);
    point p;
    for(int i=0;i<n;i++) {
        scanf("%lf%lf", &p.x , &p.y);
        points[cnt].push_back(p);
    }
    depth[cnt] = 0;
    Left[cnt] = Button[cnt] = -inf;
    Right[cnt] = Top[cnt] = inf;
    parent[cnt] = -1;
    q.push(cnt);
    while(!q.empty()) {
        int u = q.front();
        q.pop();
        vector<point> &ps = points[u];
        int sz = ps.size();
        if(sz <= 0) continue;
        if(sz == 1) {
            node[u] = ps[0];
            continue;
        }
        for(int i=0;i<sz;i++) {
            tmp[i] = ps[i];
        }
        if(depth[u] % 2 == 0) sort(tmp, tmp+sz, cmpx);
        else sort(tmp, tmp+sz, cmpy);
        int mid = sz / 2;
        node[u] = tmp[mid];
        int lsz = mid, rsz = sz - 1 - mid;
        if(lsz) {
            int l = ++cnt;
            tree[u][0] = l;
            parent[l] = u;
            depth[l] = depth[u] + 1;
            q.push(l);
            for(int i=0;i<mid;i++) points[l].push_back(tmp[i]);
            Left[l] = Left[u]; Right[l] = Right[u]; Top[l] = Top[u]; Button[l] = Button[u];
            if(depth[u] % 2 == 0) Right[l] = tmp[mid].x;
            else Top[l] = tmp[mid].y;
        }
        if(rsz) {
            int r = ++cnt;
            tree[u][1] = r;
            parent[r] = u;
            depth[r] = depth[u] + 1;
            q.push(r);
            for(int i=mid+1;i<sz;i++) points[r].push_back(tmp[i]);
            Left[r] = Left[u]; Right[r] = Right[u]; Top[r] = Top[u]; Button[r] = Button[u];
            if(depth[u] % 2 == 0) Left[r] = tmp[mid].x;
            else Button[r] = tmp[mid].y;
        }

    }
    scanf("%lf%lf", &p0.x, &p0.y);
    back_method();

    printf("(%.2lf,%.2lf)\n", node[ansid].x, node[ansid].y);

    //debug_dfs(0);
    return 0;
}

void go_method() {
    int cur = 0;
    ansid = cur;
    while(true) {
        int l = tree[cur][0], r = tree[cur][1];
        if(l && Left[l] <= p0.x && Right[l] >= p0.x && Button[l] <= p0.y && Top[l] >= p0.y) {
            cur = l;
            ansid = l;
        } else if(r && Left[r] <= p0.x && Right[r] >= p0.x && Button[r] <= p0.y && Top[r] >= p0.y) {
            cur = r;
            ansid = r;
        } else {
            R = sqrt((p0.x-node[ansid].x)*(p0.x-node[ansid].x)+(p0.y-node[ansid].y)*(p0.y-node[ansid].y));
            return;
        }
    }
}

bool should_go(int u) {
    double dd, tt;
    dd = fabs(p0.x - Left[u]);
    if(dd < R) {
        tt = sqrt(R*R-dd*dd);
        if(p0.y-tt > Button[u] && p0.y-tt < Top[u]) return true;
        if(p0.y+tt > Button[u] && p0.y+tt < Top[u]) return true;
        if(Button[u] > p0.y-tt && Button[u] < p0.y+tt) return true;
        if(Top[u] > p0.y-tt && Top[u] < p0.y+tt) return true;
    }
    dd = fabs(p0.x - Right[u]);
    if(dd < R) {
        tt = sqrt(R*R-dd*dd);
        if(p0.y-tt > Button[u] && p0.y-tt < Top[u]) return true;
        if(p0.y+tt > Button[u] && p0.y+tt < Top[u]) return true;
        if(Button[u] > p0.y-tt && Button[u] < p0.y+tt) return true;
        if(Top[u] > p0.y-tt && Top[u] < p0.y+tt) return true;
    }
    dd = fabs(p0.y - Button[u]);
    if(dd < R) {
        tt = sqrt(R*R-dd*dd);
        if(p0.x-tt > Left[u] && p0.x+tt < Right[u]) return true;
        if(p0.x+tt > Left[u] && p0.x+tt < Right[u]) return true;
        if(Left[u] > p0.x-tt && Left[u] < p0.x+tt) return true;
        if(Right[u] > p0.x-tt && Right[u] < p0.x+tt) return true;
    }
    dd = fabs(p0.y - Top[u]);
    if(dd < R) {
        tt = sqrt(R*R-dd*dd);
        if(p0.x-tt > Left[u] && p0.x+tt < Right[u]) return true;
        if(p0.x+tt > Left[u] && p0.x+tt < Right[u]) return true;
        if(Left[u] > p0.x-tt && Left[u] < p0.x+tt) return true;
        if(Right[u] > p0.x-tt && Right[u] < p0.x+tt) return true;
    }
    return false;
}

void dfs(int u) {
    double _x = node[u].x, _y = node[u].y;
    double _r = sqrt((_x-p0.x)*(_x-p0.x)+(_y-p0.y)*(_y-p0.y));
    if(_r < R) {
        R = _r;
        ansid = u;
    }
    int l = tree[u][0], r = tree[u][1];
    if(l && should_go(l)) dfs(l);
    if(r && should_go(r)) dfs(r);
    return;
}

void back_method() {
    go_method();
    int cur = ansid, precur;
    while(cur != 0) {
        precur = cur;
        cur = parent[cur];
        int l = tree[cur][0], r = tree[cur][1];
        if(precur == l && r && should_go(r)) dfs(r);
        else if(precur == r && l && should_go(l)) dfs(l);
    }
}

void debug_dfs(int u) {
    printf("dep[%d] = %d; (%.2lf,%.2lf); left:%.2lf,right:%.2lf,button:%.2lf,top:%.2lf\n",
            u, depth[u], node[u].x , node[u].y, Left[u], Right[u], Button[u], Top[u]);
    int l = tree[u][0], r = tree[u][1];
    if(l) debug_dfs(l);
    if(r) debug_dfs(r);
}

 

posted on 2015-09-06 16:01  wuyouwulv  阅读(402)  评论(0编辑  收藏  举报