SGU128 Snake

SGU128,题意是给定N个点,问说能不能形成一个闭环G,要求G经过每个点,且在每个点处都有90度的转角,且不能出现自交。

没想出来,通过提供的思路,由于每个点处都需要90度的转弯,因此每个点处必然有一条横向以及一条纵向的路径穿过,单从某个x来看,由于上述限制,因此需要有偶数个点两两配对。然后通过搜索判断是否连通,最后再借助树状数组判断是否有自交的情况(”+”这种自交形状)出现。

PS: 里有个GDB的简单教程。

#include <iostream>
#include <algorithm>
#include <vector>
using namespace std;

const int MAXN = 10005;

pair<int, int> points[MAXN];
vector<int> x_points[2*MAXN], y_points[2*MAXN];
int x_link[MAXN], y_link[MAXN];
bool visit[MAXN], towards[2*MAXN];

class BinaryIndexedTree {
private:
    int *c_, num_;
public:
    BinaryIndexedTree() : c_(NULL) {}
    BinaryIndexedTree(int num) : num_(num) {
        c_ = new int[num_];
        memset(c_, 0, sizeof(int) * num_);
    }
    ~BinaryIndexedTree() {
        if (c_ != NULL) {
            delete[] c_;
            c_ = NULL;
        }
    }
private:
    int lowbit(int x) {
        return x & (-x);
    }
public:
    int Query(int i) {
        int res = 0;
        while (i > 0) {
            res += c_[i];
            i -= this->lowbit(i);
        }
        return res;
    }
    int Query(int left, int right) {
        return this->Query(right) - this->Query(left - 1); 
    }
    void Update(int i, int value) {
        while (i < num_) {
            c_[i] += value;
            i += this->lowbit(i);
        } 
    }
};

bool x_cmp(int u, int v) {
    return points[u].first < points[v].first;
}

bool y_cmp(int u, int v) {
    return points[u].second < points[v].second;
}

int main()
{
    int n;
    scanf("%d", &n);
    for (int i = 0; i < n; i++) {
        int a, b;
        scanf("%d%d", &a, &b);
        a += 10001;
        b += 10001;

        points[i].first = a;
        points[i].second = b;

        x_points[a].push_back(i);
        y_points[b].push_back(i);
    }

    bool ok = true;
    int total_length = 0;
    memset(x_link, -1, sizeof(x_link));
    memset(y_link, -1, sizeof(y_link));

    do {
        // x order 
        for (int i = 0; i < 2 * MAXN; i++) {
            if (x_points[i].size() > 0) {
                if (x_points[i].size() & 1) {
                    ok = false;
                    break;
                }
               
                sort(x_points[i].begin(), x_points[i].end(), y_cmp);
                
                for (int j = 0; j < x_points[i].size(); j += 2) {
                    int down = x_points[i][j];
                    int up = x_points[i][j + 1];

                    total_length += (points[up].second - points[down].second);

                    y_link[down] = up; y_link[up] = down;
                }
            }
        }        
        if (!ok)  break;

        // y order
        for (int i = 0; i < 2 * MAXN; i++) {
            if (y_points[i].size() > 0) {
                if (y_points[i].size() & 1) {
                    ok = false;
                    break;
                }
               
                sort(y_points[i].begin(), y_points[i].end(), x_cmp);
                
                for (int j = 0; j < y_points[i].size(); j += 2) {
                    int left = y_points[i][j];
                    int right = y_points[i][j + 1];

                    total_length += (points[right].first - points[left].first);

                    x_link[left] = right; x_link[right] = left;
                }
            }
        }        
        if (!ok)  break;

        // search
        memset(visit, false, sizeof(visit));
        vector<int> Q;
        Q.push_back(0);
        visit[0] = true;

        for (int i = 0; i < Q.size(); i++) {
            if (x_link[Q[i]] == -1 || y_link[Q[i]] == -1) {
                ok = false;
                break;
            } else {
                if (visit[x_link[Q[i]]] == false) {
                    visit[x_link[Q[i]]] = true;
                    Q.push_back(x_link[Q[i]]);
                } 

                if (visit[y_link[Q[i]]] == false) {
                    visit[y_link[Q[i]]] = true;
                    Q.push_back(y_link[Q[i]]);
                }
            }
        }

        for (int i = 0; i < n; i++) {
            if (visit[i] == false) {
                ok = false;
                break;
            }
        }

        // check self-cross
        memset(towards, false, sizeof(towards));
        BinaryIndexedTree tree = BinaryIndexedTree(MAXN * 2);
        for (int i = 0; i < 2*MAXN; i++) if (x_points[i].size() > 0) {
            for (int j = 0; j < x_points[i].size(); j += 2) {
                int down = points[x_points[i][j]].second;
                int up = points[x_points[i][j + 1]].second;

                towards[down] = !towards[down];
                towards[up] = !towards[up];

                tree.Update(down, towards[down] ? +1 : -1);
                tree.Update(up, towards[up] ? +1 : -1);

                if (down + 1 < up - 1 && tree.Query(down + 1, up - 1) > 0) {
                    ok = false;
                    break;
                }
            } 

            if (!ok)  break;
        }

    } while(0);

    if (ok) {
        printf("%d\n", total_length);
    } else {
        printf("0\n");
    }
}

 

posted @ 2013-08-11 23:16  litstrong  阅读(260)  评论(0编辑  收藏  举报