luogu P3645 [APIO2015]ジャカルタの超高層ビル

luogu

暴力?

暴力!

質問のような最短ビットので、配置(F_ {I、J}は\ \) を表し\を(私は\)現在の建物\を(ドージェ\)ジャンプ能力\(J \)ステップ、転送の最小数であるか、またはステップジャンプ\(F_が{iがJ + \ J}) および\({F_のIJ、J}を\) または別の変更\(ドージェ\)に進み、(F_ {I、K} \ \)

これは持っているように見えます\(N ^ 2 \)状態、実際には、状態の数だけ\(N- \ sqrtの\ N-) ので\(pは> \ sqrtのN \ ) とき\(元首が\)だけジャンプすることができます\(N \ SQRT \)異なる点は、これはに分割されている\(Mする\ n-SQRT \) ;もし\(P \ル\ SQRT N \) 場合、理由\(J \ル\ N-SQRT \) そう状態の総数\(N \ N-SQRT \) 次いで用エッジの数、右側0/1の2つだけの種類、各状態の両側の最大値、及びエッジ0(すなわち\(ドージェ\))、明らかにそれぞれのための\(Iは\)のみで\(F_ {I、J} \) 最小遷移状態良好、そうである転送の総数\(N \ SQRT N \)

両端キューが最短0/1を達成した場合に達成することができます。また、アクセス状態、かどうかを判断する必要が\(3万3万*の\)\(BOOL \)配列が高いオープニングを、することが可能である(ビットセットを\)\

#include<bits/stdc++.h>
#define LL long long
#define uLL unsigned long long
#define db double

using namespace std;
const int N=30000+10;
int rd()
{
    int x=0,w=1;char ch=0;
    while(ch<'0'||ch>'9'){if(ch=='-') w=-1;ch=getchar();}
    while(ch>='0'&&ch<='9'){x=(x<<3)+(x<<1)+(ch^48);ch=getchar();}
    return x*w;
}
bitset<N> v[N];
int n,m,ps,ans=1<<30;
vector<int> dog[N];
struct node
{
    int x,j,d;
};
deque<node> q;

int main()
{
    n=rd(),m=rd();
    int b=rd()+1,p=rd();
    v[b][p]=1,q.push_front((node){b,p,0});
    for(int i=1;i<m;++i)
    {
        b=rd()+1,p=rd();
        if(i==1) ps=b;
        dog[b].push_back(p);
    }
    while(!q.empty())
    {
        int x=q.front().x,j=q.front().j,d=q.front().d;
        q.pop_front();
        if(x==ps) ans=min(ans,d);
        vector<int>::iterator it;
        for(it=dog[x].begin();it!=dog[x].end();++it)
        {
            int y=*it;
            if(!v[x][y]) v[x][y]=1,q.push_front((node){x,y,d});
        }
        dog[x].clear();
        if(x-j>=1&&!v[x-j][j]) v[x-j][j]=1,q.push_back((node){x-j,j,d+1});
        if(x+j<=n&&!v[x+j][j]) v[x+j][j]=1,q.push_back((node){x+j,j,d+1});
    }
    printf("%d\n",ans<(1<<30)?ans:-1);
    return 0;
}

おすすめ

転載: www.cnblogs.com/smyjr/p/11618620.html