POJ 2991クレーン(+計算幾何セグメントツリー)

説明

ACMは、新しいクレーン( - jeřábクレーン)を購入しました。クレーンは、フレキシブルジョイントにより接続された様々な長さのN個のセグメントで構成されています。i番目のセグメントの端部は、1≤I <nに対して、I + 1番目の一方の先頭に接合されています。最初のセグメントの開始は、最初のセグメントの長さであり、ここで、W、(W、0)を座標(0、0)と座標点で、その端部に点で固定されています。セグメントのすべてが1つの平面内に常に存在し、関節は、その平面内の任意の回転を可能にします。不快な事故の一連の後、それはクレーンが常にクレーンの端部の位置を確認し、衝突が起こる必要がある場合は、クレーンを停止するコードの一部を含んでいなければならないソフトウェアで制御することを決定しました。

あなたの仕事は、各コマンドの後にn番目のセグメントの端部の位置を決定し、このソフトウェアの一部を記述することです。クレーンの状態は、連続セグメント間の角度によって決定されます。最初は、角度のすべてがストレート、すなわち、180°です。正確に一つの関節の角度を変更するオペレータの問題コマンド。
入力

入力は、単一の空行で区切られた複数のインスタンスからなります。

各インスタンスの最初の行は二つの整数1から成る≤N≤10000とC 0単一スペースで区切ら-クレーンやコマンドの数のセグメントの数。2行目では、nは整数でL1の、...、LN(1つの李100)は、単一のスペースで区切られ構成されています。クレーンのi番目のセグメントの長さは、Liです。次のCラインは、オペレータのコマンドを指定します。コマンドを記述する各行は二つの整数Sからなり、(1≤S <N、0≤≤359)は、単一のスペースで区切ら- S番目とs + 1番目のセグメントとの間の角度を変化させるために度(角度はS + 1番目のセグメントに対するs番目から反時計回りに測定されます)。
出力

各インスタンスの出力はC線で構成されています。行のi番目のは、二つの有理数で構成され、XおよびYは、単一のスペースで区切られた - i番目のコマンドの後にn番目のセグメントの端部の座標は、小数点以下2桁に丸め。

各二つの連続するインスタンスの出力は、単一の空行によって分離されなければなりません。
サンプル入力

2 1
10 5
1 90

3 2
5 5
1 270
2 90
サンプル出力

5.00 10.00

-10.00 5.00
-5.00 10.00
ソース

CTUオープン2005

質問の意味:
理解することが少し難しい感じの問題の意味を。これは各スティックの長さを与え、そして順次Y軸に取り付けられました。最初の出発点は、スティック(0,0)であり、
X及びX + 1スティックの反時計回りの角度、180度の初期角度を変化させるm個の質問回、各回。
常にスティックに最終出力座標の終了をお願いします。X及びX + 1スティック角、スティックの後ろにX + 1の方向の実際の調整を調整するとき。
アイデア:
セグメントツリーは、角度変換であり、一つは終点座標であり、二つの情報を維持します。
初期座標の端が同定されている実際には、各調整は、終点座標の角度に影響を与えます。
度[x]は、一緒に座標変換ベクトルの式-角度の各調整は、Y得
newx = X * COS(RAD) - Y * SIN(RAD)
newyはSiN = X *(RAD)+ Y * COSを(RAD)
更新には、更新は、実際にはX + 1〜Nです。

#include <cstdio>
#include <cstring>
#include <algorithm>
#include <cmath>

using namespace std;

const int maxn = 1e4 + 7;
const double PI = acos(-1);
double len[maxn],degree[maxn];
struct Node
{
    int l,r;
    double d;
    double x,y;
}t[maxn << 2];

void Rotate(int i,int r)
{
    double rad = r / 180.0 * PI;
    double newx = t[i].x * cos(rad) - t[i].y * sin(rad);
    double newy = t[i].x * sin(rad) + t[i].y * cos(rad);
    t[i].x = newx;t[i].y = newy;
}

void pushup(int i)
{
    t[i].x = t[i * 2].x + t[i * 2 + 1].x;
    t[i].y = t[i * 2].y + t[i * 2 + 1].y;
}

void pushdown(int i)
{
    if(t[i].d)
    {
        t[i * 2].d += t[i].d;
        t[i * 2 + 1].d += t[i].d;
        Rotate(i * 2,t[i].d);
        Rotate(i * 2 + 1,t[i].d);
        t[i].d = 0;
    }
}

void build(int i,int l,int r)
{
    t[i].l = l;t[i].r = r;
    t[i].d = 0;
    if(l == r)
    {
        t[i].x = 0;
        t[i].y = len[l];
        return;
    }
    int m = (l + r) >> 1;
    build(i * 2,l,m);
    build(i * 2 + 1,m + 1,r);
    pushup(i);
}

void update(int i,int x,double v)
{
    if(x <= t[i].l)
    {
        Rotate(i,v);
        t[i].d += v;
        return;
    }
    pushdown(i);
    int m = (t[i].l + t[i].r) >> 1;
    if(x <= m)update(i * 2,x,v);
    update(i * 2 + 1,x,v);
    pushup(i);
}

int main()
{
    int n,m;
    while(~scanf("%d%d",&n,&m))
    {
        for(int i = 1;i <= n;i++)
        {
            scanf("%lf",&len[i]);
            degree[i] = 180.0;
        }
        build(1,1,n);
        while(m--)
        {
            int x;
            double y;scanf("%d%lf",&x,&y);
            update(1,x + 1,y - degree[x]);
            degree[x] = y;
            double ansx = fabs(t[1].x) < 1e-8 ? 0 : t[1].x;
            double ansy = fabs(t[1].y) < 1e-8 ? 0 : t[1].y;
            printf("%.2f %.2f\n",ansx,ansy);
        }
        printf("\n");
    }
    return 0;
}

公開された676元の記事 ウォン称賛18 ビュー30000 +

おすすめ

転載: blog.csdn.net/tomjobs/article/details/104102330