ZROI#1012

ZROI#1012

ZROI#1012

考虑如果没有 \(backspace\) 操作,那就是个 \(SB\) 递推.

考虑加入 \(backspce\) 后有什么影响,那就是出现环状转移.

那咋办,显然所有的转移一定都是正权,也就是不会有一种转移,使状态变化的同时减少答案次数.

我们知道,平时 \(DP\) 的转移就是一张边带权的 \(DAG\) , 我们要求的答案其实就是这张 \(DAG\) 上从起始点到目标点的最短/长路.

那么这个题,我们不如就把这样一张转移图建出来,直接采用 \(SPFA\) 的方式以重复入队来完成转移,因为一定会有一些状态是不在环中的,所以环上的状态可以通过多次入队调整松弛完成最优化.

建边的时候要考虑全面,漏掉一种边很可能就会收获 \(0pts\) 的好成绩.

\(backspace\) 操作肯定不会有很多,所以边数并不巨大,理论上需要 \(n\times log_2{n}\) 条,而实际只需要向后 \(\times 5\) 就能 \(AC\).(多了会 \(TLE\))

当然,可能某些人的代码需要卡卡常.

#pragma GCC optimize(2)
#pragma GCC optimize(3)
#pragma GCC target("sse,sse2,sse3,sse4.1,sse4.2,popcnt,abm,mmx,avx")
#pragma comment(linker,"/STACK:102400000,102400000")
#pragma GCC optimize("Ofast")
#pragma GCC optimize("inline")
#pragma GCC optimize("-fgcse")
#pragma GCC optimize("-fgcse-lm")
#pragma GCC optimize("-fipa-sra")
#pragma GCC optimize("-ftree-pre")
#pragma GCC optimize("-ftree-vrp")
#pragma GCC optimize("-fpeephole2")
#pragma GCC optimize("-ffast-math")
#pragma GCC optimize("-fsched-spec")
#pragma GCC optimize("unroll-loops")
#pragma GCC optimize("-falign-jumps")
#pragma GCC optimize("-falign-loops")
#pragma GCC optimize("-falign-labels")
#pragma GCC optimize("-fdevirtualize")
#pragma GCC optimize("-fcaller-saves")
#pragma GCC optimize("-fcrossjumping")
#pragma GCC optimize("-fthread-jumps")
#pragma GCC optimize("-funroll-loops")
#pragma GCC optimize("-fwhole-program")
#pragma GCC optimize("-freorder-blocks")
#pragma GCC optimize("-fschedule-insns")
#pragma GCC optimize("inline-functions")
#pragma GCC optimize("-ftree-tail-merge")
#pragma GCC optimize("-fschedule-insns2")
#pragma GCC optimize("-fstrict-aliasing")
#pragma GCC optimize("-fstrict-overflow")
#pragma GCC optimize("-falign-functions")
#pragma GCC optimize("-fcse-skip-blocks")
#pragma GCC optimize("-fcse-follow-jumps")
#pragma GCC optimize("-fsched-interblock")
#pragma GCC optimize("-fpartial-inlining")
#pragma GCC optimize("no-stack-protector")
#pragma GCC optimize("-freorder-functions")
#pragma GCC optimize("-findirect-inlining")
#pragma GCC optimize("-fhoist-adjacent-loads")
#pragma GCC optimize("-frerun-cse-after-loop")
#pragma GCC optimize("inline-small-functions")
#pragma GCC optimize("-finline-small-functions")
#pragma GCC optimize("-ftree-switch-conversion")
#pragma GCC optimize("-foptimize-sibling-calls")
#pragma GCC optimize("-fexpensive-optimizations")
#pragma GCC optimize("-funsafe-loop-optimizations")
#pragma GCC optimize("inline-functions-called-once")
#pragma GCC optimize("-fdelete-null-pointer-checks")
#include <algorithm>
#include <iostream>
#include <cstdlib>
#include <cstring>
#include <cstdio>
#include <string>
#include <vector>
#include <queue>
#include <cmath>
#include <ctime>
#include <map>
#include <set>
#define MEM(x,y) memset ( x , y , sizeof ( x ) )
#define rep(i,a,b) for (int i = (a) ; i <= (b) ; ++ i)
#define per(i,a,b) for (int i = (a) ; i >= (b) ; -- i)
#define pii pair < int , int >
#define one first
#define two second
#define rint read<int>
#define pb push_back
#define db double
#define ull unsigned long long
#define lowbit(x) ( x & ( - x ) )

using std::queue ;
using std::set ;
using std::pair ;
using std::max ;
using std::min ;
using std::priority_queue ;
using std::vector ;
using std::swap ;
using std::sort ;
using std::unique ;
using std::greater ;

template < class T >
    inline T read () {
        T x = 0 , f = 1 ; char ch = getchar () ;
        while ( ch < '0' || ch > '9' ) {
            if ( ch == '-' ) f = - 1 ;
            ch = getchar () ;
        }
       while ( ch >= '0' && ch <= '9' ) {
            x = ( x << 3 ) + ( x << 1 ) + ( ch - 48 ) ;
            ch = getchar () ;
       }
       return f * x ;
    }

const int N = 1e7 + 100 ;
const int inf = 0x7f7f7f7f ;
struct edge { int to , next , data ; } e[N<<1] ;

queue < int > q ;
int n , x , dis[N] , head[N] , tot , maxn = - inf ;
bool vis[N] ;

inline void build (int u , int v , int w) {
    e[++tot].next = head[u] ; e[tot].to = v ;
    e[tot].data = w ; head[u] = tot ; return;
}

inline void SPFA (int cur) {
    MEM ( dis , 0x7f ) ; MEM ( vis , 0 ) ;
    q.push ( cur ) ; vis[cur] = true ; dis[cur] = 0 ;
    while ( ! q.empty () ) {
        int j = q.front () ; q.pop () ; vis[j] = false ;
        for (int i = head[j] ; i ; i = e[i].next) {
            int k = e[i].to ;
            if ( dis[k] > dis[j] + e[i].data ) {
                dis[k] = dis[j] + e[i].data ;
                if ( ! vis[k] ) q.push ( k ) , vis[k] = true ;
            }
        }
    }
    return ;
}

signed main (int argc , char * argv[]) {
    x = rint () ; n = rint () ; maxn = max ( n , x ) + 1 ;
    rep ( i , 0 , maxn ) {
        build ( i , i + 1 , 1 ) ;
        build ( i , i - 1 , 1 ) ;
        build ( i , 0 , 3 ) ;
    }
    rep ( i , 1 , maxn )
        for (int j = 1 ; j <= 5 && i * j <= maxn ; ++ j)
            build ( i , i * j , 4 + 2 * ( j - 1 ) ) ;
    SPFA ( x ) ; printf ("%lld\n" , dis[n] ) ;
    return 0 ;
}
posted @ 2019-10-22 14:49  Phecda  阅读(84)  评论(0)    收藏  举报

Contact with me