コインスライダー

タイトル説明

あなたはコインパズルをプレイしています。次のようにこのパズルのルールは次のとおりです。

Nコインがテーブルの上にあります。i番目の硬貨は、RI半径を有する円であり、その中心は、最初(SXI、SYI)に配置されています。各コインはまた、目標位置があります。その中心が(TXI、TYI)であるように、あなたは、i番目のコインを移動する必要があります。あなたはコインを一つずつ移動することができますし、高々一度各コインを移動することができます。あなたがコインを移動すると、それは直線に沿ってその目標位置にその初期位置から移動しなければなりません。また、コインは移動の途中に含め、相互に衝突することができません。

パズルのスコアは、あなたが彼らの目標位置にその初期位置から移動するコインの枚数です。あなたの仕事は、与えられたパズルのインスタンスの最大スコアを決定するプログラムを書くことです。

エントリー

入力は、次のようにフォーマットされた単一のテストケースから構成されています。

N
R1 SX1のSY1のTX1のTY1

RN SXN SYN TX1ティン
最初の行は、パズルに使用されるコインの数である整数N(1≤N≤16)を含みます。次のN行のi番目の行は、5つの整数から成る:RI、SXI、SYI、TXI、及びTYI(1≤ri≤1,000、-1,000≤sxi、SYI、TXI、tyi≤1,000、(SXI、SYI) ≠(TXI、TYI))。彼らは、i番目の硬貨の情報を記述:riはi番目のコイン、(SXI、SYI)の半径は、i番目の硬貨の初期位置である、及び(TXI、TYIは)の目標位置でありますi番目のコイン。

あなたはコインが接触していないか、初期位置に重ならないと仮定することができます。また、最大スコアは10-5で各コインの変更の場合でも半径を変更しないと仮定することができます。

輸出

ラインで与えられたパズルのインスタンスの最大スコアを印刷します。

サンプル入力

3 
2 0 0 1 0 
2 0 5 1〜5 
4 1 -10 10 -5

サンプル出力

2
質問の意味:
あなたのN-を与えるために(N- <= 16 )中心座標と半径、およびセンターは、彼らが先の座標ラウンド
先の交差点に到達できないか、他の多くのラウンドとラウンドまで尋ね
のみとだけ直線を歩くことができる円を先に移動する

アイデア:
直接BFSを、2 ^ int型16は、現在の状況を記録し、円が次の状態に拡張することが可能と交差することなく、他の目的地に移動させることができるサークル確認するために
主な問題は丸い先を移動するための方法を決定することです他の円形の交差点となります
円プラス円の現在の半径の他の半径、問題は問題と交差する需要中心線(ライン)と、他の円に変換された
線分の終点がある場合には内側の円内の特定の交点であります
半径が一定の互いに素より大きい線分の中心からの距離場合
、または中心点の両端は角度であるが鋭角であり、それが交差しなければならない

私は二晩揚げダブル、INT曲と(Zaozhidaojiuを
#include <ビット/ STDC ++ H>
 の#defineは長い長いllの
 使用 名前空間STDを、
const  int型 N = 200 ;
int型nは、ANS;
構造体ポイント{ 
    LLのX、Y。
    ポイント(){} 
    点(LL _x、LL _y)
    { 
        X = _x。Y = _y。
    } 
    ポイント演算子 - (CONSTポイント&B)のconst 
    { 
        返す(Y、xb.xポイントによって)。
    } 
    LL 演算子 *(CONSTポイント&B)のconst 
    {
        戻り * Y X * b.x + することにより、
    } 
} P1 [N]、P2 [N]。
構造体ORZ {
     int型、S、D;}; 
[N] R LL。
キュー <ORZ> Q;
BOOL VIS [ 1 << 20 ]。
LL DIS(A点、B点)
{ 
    リターン(AB)*(AB )。
} 
BOOLインター(int型 I、int型 J、int型のOP)
{ 
    ポイントO。
    もし(OP == 1)O = P2 [J]。他の O = P1 [J]。
    ポイントO1 = P1 [i]は、O2 = P2の[i]は、
    INT R = R [J] + R [i]は、
    もし(DIS(O1、O)<R * R || DIS(O2、O)<R * R)戻り 0 ; 

    LL、B、C、DIS1、DIS2、のAng1、Ang2と; 
    もし(O1.x == O2.x)、A = 1、B = 0、C = - O1.x。
    そう であれば(O1.y == O2.y)A = 0、B = 1、C = - O1.y。
    他に = O1.y-O2.y、B = O2.x-O1.x、C = O1.x * O2.y-O1.y * O2.x。

    DIS1 = A * O.x + B * O.y + C。
    DIS1 * = DIS1。
    DIS2 =(*はA + B * B)*(R * R)。
    もし(DIS1> = DIS2)リターン 1 

    Ang1 =(OX-O1.x)*(O2.x-O1.x)+(オイ- O1.y)*(O2.y- O1.y)。
    Ang2 =(OX-O2.x)*(O1.x-O2.x)+(オイ- O2.y)*(O1.y- O2.y)。
    もし(Ang1を> 0 &&のAng2> 0の戻り 0 ;
    リターン 1 ; 
} 
ブールチェック(int型のx、int型の)
{ 

    ブールフラグ= 1 以下のためにint型 i = 0 ; iがn <Iは、++は
    { 
        場合(I == x)を続けますもし   (S&(1<< I))フラグ&=インテル(X、I、1 )。
        他のフラグ&=インテル(X、I、2 )。
        もし(!フラグ)   ブレーク
    } 
    戻りフラグ。
} 
ボイドBFS()
{ 
    ANS = 0 
    q.push({ 00 })。
    VIS [ 0 ] = 1 しばらく(!q.empty())
    { 
        ORZ今 = q.front(); q.pop();
        // ため(INT i = 0; iがn <; iは++)COUT <<((now.s >> I)&1)。coutの<<てendl; 
        ANS =MAX(ANS、now.d)。
        以下のためにint型私= 0 ; iがn <;私は++を
        { 
            場合((now.s&(1 << I))== 0!&& VIS [now.s |(1 << I)] && チェック(I、 now.s))
            { 
                q.push({now.s |(1 << I)、now.d + 1 })。
                VIS [now.s |(1 << I)] = 1 ; 
            } 
        } 
    } 
} 
int型のmain()
{ 
    scanf関数(" %のD "、&N)
    int型 iは= 0のscanf(; iがN <I ++)は、 " %LLD%LLD%LLD%LLD%LLD "、およびR [i]は、&​​P1 [i]は.X、&P1 [i]は.Y、&P2 [I ] .X、&P2 [I] .Y)。
    BFS(); 
    printf(" %d個の\ n " 、ANS)。
    リターン 0 ; 
}
コードの表示

 

 

おすすめ

転載: www.cnblogs.com/tetew/p/11391843.html