URAL 1130 Nikifor's Walk

来源:互联网 发布:剑网三长歌门捏脸数据 编辑:程序博客网 时间:2024/06/16 14:57

http://acm.timus.ru/problem.aspx?space=1&num=1130

题意

出n个向量,长度均L,问能否通过添加+ or 号,使得求和以后长度2L

题解

通过画图,可以发现,任意三个长度L的向量,通过适当的+ or ,其中必有两个可以凑出L的一个新向量。
如此做,最后剩下两个,此时再添加+ or ,必能凑出长度2L的向量

code

#include <algorithm>#include <bitset>#include <cassert>#include <cmath>#include <cstdio>#include <cstdlib>#include <cstring>#include <ctime>#include <deque>#include <iostream>#include <map>#include <queue>#include <set>#include <string>#include <vector>typedef long long LL;const int maxn = 10010;struct Point {    int x, y;    Point() { }    Point(int x, int y) : x(x), y(y) { }} A[maxn << 1];Point operator +(const Point& A, const Point& B)    { return Point(A.x+B.x, A.y+B.y); }Point operator -(const Point& A, const Point& B)    { return Point(A.x-B.x, A.y-B.y); }int Length2(const Point& A) { return A.x * A.x + A.y * A.y; }int N, n, L;int sk[maxn], tp;int tot;int st[maxn << 1], lk[maxn << 1], b[maxn << 1], c[maxn << 1];void addedge(int u, int v, int w) {    lk[++ tot] = st[u]; b[tot] = v; c[tot] = w; st[u] = tot;}char opt[maxn];void dfs(int u, char p) {    if (u < N) opt[u] = p;    for (int i = st[u]; i; i = lk[i])        dfs(b[i], c[i] ? (p == '+' ? '-' : '+') : p);}void solve() {    scanf("%d%d", &N, &L); L *= L;    for (int i = 0; i < N; ++ i)        scanf("%d%d", &A[i].x, &A[i].y);    tp = 0;    for (int i = 0; i < N; ++ i) sk[tp ++] = i;    n = N;    while (tp > 1) {        int v1 = sk[tp-1], v2 = sk[tp-2];        if (tp > 2) {            int v3 = sk[tp-3]; tp -= 3;            if (Length2(A[v1]+A[v2]) <= L) { A[n ++] = A[v1]+A[v2]; sk[tp ++] = v3; sk[tp ++] = n-1; addedge(n-1, v1, 0); addedge(n-1, v2, 0); continue; }            if (Length2(A[v1]-A[v2]) <= L) { A[n ++] = A[v1]-A[v2]; sk[tp ++] = v3; sk[tp ++] = n-1; addedge(n-1, v1, 0); addedge(n-1, v2, 1); continue; }            std::swap(v2, v3);            if (Length2(A[v1]+A[v2]) <= L) { A[n ++] = A[v1]+A[v2]; sk[tp ++] = v3; sk[tp ++] = n-1; addedge(n-1, v1, 0); addedge(n-1, v2, 0); continue; }            if (Length2(A[v1]-A[v2]) <= L) { A[n ++] = A[v1]-A[v2]; sk[tp ++] = v3; sk[tp ++] = n-1; addedge(n-1, v1, 0); addedge(n-1, v2, 1); continue; }            std::swap(v1, v3);            if (Length2(A[v1]+A[v2]) <= L) { A[n ++] = A[v1]+A[v2]; sk[tp ++] = v3; sk[tp ++] = n-1; addedge(n-1, v1, 0); addedge(n-1, v2, 0); continue; }            if (Length2(A[v1]-A[v2]) <= L) { A[n ++] = A[v1]-A[v2]; sk[tp ++] = v3; sk[tp ++] = n-1; addedge(n-1, v1, 0); addedge(n-1, v2, 1); continue; }        } else {            tp -= 2;            if (Length2(A[v1]+A[v2]) <= L*2) { A[n ++] = A[v1]+A[v2]; sk[tp ++] = n-1; addedge(n-1, v1, 0); addedge(n-1, v2, 0); continue; }            if (Length2(A[v1]-A[v2]) <= L*2) { A[n ++] = A[v1]-A[v2]; sk[tp ++] = n-1; addedge(n-1, v1, 0); addedge(n-1, v2, 1); continue; }        }//      assert(0);    }//  assert(Length2(A[0]) <= L*2);    puts("YES");    dfs(n-1, '+');    for (int i = 0; i < N; ++ i) putchar(opt[i]);    putchar('\n');}int main() {//  freopen("G.in", "r", stdin);//  freopen("G_2.out", "w", stdout);    solve();//  for(;;);    return 0;}
0 0