zoukankan      html  css  js  c++  java
  • 【BZOJ4070】[APIO2015] 雅加达的摩天楼(BFS)

    点此看题面

    大致题意:(n)个点以及(m)(doge)(大概是某种神奇生物?),第(i)(doge)最初在第(a_i)个点,每次能向左或向右跳(b_i)个点。当两个(doge)在某位置相遇时,可以改为另一只(doge)跳动。求从第(1)(doge)所在位置出发,至少经过多少步才能跳到第(2)(doge)所在位置。

    前言

    emmm,这道题说是分块题,结果最后好像只是用分块的思想来证明复杂度?

    (BFS)跑得飞快,只是这题卡(set),害得我不得不改成(bitset)

    简单粗暴的(BFS)

    我们设状态((a,b)),表示当前的(doge)在第(a)个点,跳动能力是(b)

    然后要注意对于每一个点,只有当我们第一次(BFS)到时,需要判断是否改为由这个点上的(doge)跳动,因为越早改肯定越优。

    复杂度证明

    考虑由于是(BFS),每个状态只会被处理一次,因此我们只需知道状态总数,即可知道复杂度。

    • 对于(ble sqrt n),在(a=1sim n)的情况下,最多只有(nsqrt n)种状态。
    • 对于(b>sqrt n),则每一个(b)所能对应的(a)的数量小于(sqrt n),即便全部(m)(doge)(b)都大于(sqrt n),最多也只有(msqrt n)种状态。

    于是(BFS)的复杂度得到了证明。

    代码

    #include<bits/stdc++.h>
    #define Tp template<typename Ty>
    #define Ts template<typename Ty,typename... Ar>
    #define Reg 
    #define RI Reg int
    #define Con const
    #define CI Con int&
    #define I inline
    #define W while
    #define N 30000
    #define pb push_back
    using namespace std;
    int n,m,a[N+5],b[N+5],vis[N+5];vector<int> V[N+5];bitset<N+5> s[N+5];
    struct S//记录状态
    {
    	int a,b,t;I S(CI x=0,CI y=0,CI k=0):a(x),b(y),t(k){}
    };vector<S> q;
    I int BFS()
    {
    	if(a[1]==a[2]) return 0;
    	#define Try(A) (!s[A.a].test(A.b)&&(s[A.a].set(A.b),++T,q.pb(A),0))//判断是否重复,若不重复则加入队列
    	#define New(p,f) for(vis[p]=1,i=0,sz=V[p].size();i^sz;++i) nk=S(p,b[V[p][i]],f),Try(nk);//将第p个点所有doge加入队列
    	RI H=0,T=-1,i,sz;S k,nk;New(a[1],0);W(H<=T)//BFS
    	{
    		if(k=q[H++],k.a>=k.b)//向左跳
    		{
    			if(k.a-k.b==a[2]) return k.t+1;if(!vis[k.a-k.b]) New(k.a-k.b,k.t+1);
    			nk=S(k.a-k.b,k.b,k.t+1),Try(nk);
    		}
    		if(k.a+k.b<n)//向右跳
    		{
    			if(k.a+k.b==a[2]) return k.t+1;if(!vis[k.a+k.b]) New(k.a+k.b,k.t+1);
    			nk=S(k.a+k.b,k.b,k.t+1),Try(nk);
    		}
    	}return -1;//无解
    }
    int main()
    {
    	RI i;for(scanf("%d%d",&n,&m),i=1;i<=m;++i) scanf("%d%d",a+i,b+i),V[a[i]].pb(i);
    	return printf("%d",BFS()),0;
    }
    
  • 相关阅读:
    uva11922splay
    获取的二维数组排序
    二维数组排序
    $.extend
    <eq>标签
    datagrid时间插件
    id=%d是什么意思呢?
    获得某一月的第一天,最后一天
    数组合并
    phpexcel 导入导出excel表格
  • 原文地址:https://www.cnblogs.com/chenxiaoran666/p/BZOJ4070.html
Copyright © 2011-2022 走看看