码迷,mamicode.com
首页 > 其他好文 > 详细

「题解」「美团 CodeM 资格赛」跳格子

时间:2019-12-14 15:39:21      阅读:93      评论:0      收藏:0      [点我收藏+]

标签:ati   开始   signed   出栈   getc   lib   cpp   sign   span   

「题解」「美团 CodeM 资格赛」跳格子

今天真的考自闭了...

\(T1\) 花了 \(2h\) 都没有搞定,最后无奈 \(90pts\)

然而 \(T2\) 想到很多很奇怪的做法,结果正解在 \(28min\) 之内做出...

结果 \(T3\) 是本人最不擅长的期望,直接跳过,啥都没得。

来水一发 \(T1\) 的题解...

题目描述

点这里

考场思路

其实并没有什么十分特别的思路,就是一通乱搞...

看看这 \(90pts\)煞笔代码

#pragma GCC optimize(2)
#include<cstdio>
#include<cstdlib>

#define rep(i,__l,__r) for(int i=__l,i##_end_=__r;i<=i##_end_;++i)
#define fep(i,__l,__r) for(int i=__l,i##_end_=__r;i>=i##_end_;--i)
#define writc(a,b) fwrit(a),putchar(b)
#define mp(a,b) make_pair(a,b)
#define ft first
#define sd second
#define LL long long
#define ull unsigned long long
#define pii pair<int,int>
#define Endl putchar('\n')
// #define FILEOI
// #define int long long

#ifdef FILEOI
    #define MAXBUFFERSIZE 500000
    inline char fgetc(){
        static char buf[MAXBUFFERSIZE+5],*p1=buf,*p2=buf;
        return p1==p2&&(p2=(p1=buf)+fread(buf,1,MAXBUFFERSIZE,stdin),p1==p2)?EOF:*p1++;
    }
    #undef MAXBUFFERSIZE
    #define cg (c=fgetc())
#else
    #define cg (c=getchar())
#endif
template<class T>inline void qread(T& x){
    char c;bool f=0;
    while(cg<'0'||'9'<c)f|=(c=='-');
    for(x=(c^48);'0'<=cg&&c<='9';x=(x<<1)+(x<<3)+(c^48));
    if(f)x=-x;
}
inline int qread(){
    int x=0;char c;bool f=0;
    while(cg<'0'||'9'<c)f|=(c=='-');
    for(x=(c^48);'0'<=cg&&c<='9';x=(x<<1)+(x<<3)+(c^48));
    return f?-x:x;
}
template<class T,class... Args>inline void qread(T& x,Args&... args){qread(x),qread(args...);}
template<class T>inline T Max(const T x,const T y){return x>y?x:y;}
template<class T>inline T Min(const T x,const T y){return x<y?x:y;}
template<class T>inline T fab(const T x){return x>0?x:-x;}
inline int gcd(const int a,const int b){return b?gcd(b,a%b):a;}
inline void getInv(int inv[],const int lim,const int MOD){
    inv[0]=inv[1]=1;for(int i=2;i<=lim;++i)inv[i]=1ll*inv[MOD%i]*(MOD-MOD/i)%MOD;
}
template<class T>void fwrit(const T x){
    if(x<0)return (void)(putchar('-'),fwrit(-x));
    if(x>9)fwrit(x/10);putchar(x%10^48);
}
inline LL mulMod(const LL a,const LL b,const LL mod){//long long multiplie_mod
    return ((a*b-(LL)((long double)a/mod*b+1e-8)*mod)%mod+mod)%mod;
}

const int MAXN=1e5;

class task{
private:
    int N,tail;
    int a[MAXN+5],b[MAXN+5],pre[MAXN+5];
    bool infty,vis[MAXN+5];
    char st[MAXN<<4];

    inline bool inside(const int p){
        return 0<p && p<=N;
    }

    inline bool putAns(){
        if(tail<1)return false;
        rep(i,1,tail)putchar(st[i]);
        return true;
    }

    inline void dfs(const int p){
        if(vis[p])return;
        vis[p]=true;
        if(p==N)exit(putAns()&0);
        if(inside(p+a[p])){
            if(pre[p+a[p]]==p)infty=true;
            else{
                int num=pre[p+a[p]];
                pre[p+a[p]]=p;
                st[++tail]='a';
                dfs(p+a[p]);
                --tail;
                pre[p+a[p]]=num;
            }
        }
        if(inside(p+b[p])){
            if(pre[p+b[p]]==p)infty=true;
            else{
                int num=pre[p+b[p]];
                pre[p+b[p]]=p;
                st[++tail]='b';
                dfs(p+b[p]);
                --tail;
                pre[p+b[p]]=num;
            }
        }
    }

    inline void getVis(const int p){
        vis[p]=true;
        if(inside(p+a[p]) && !vis[p+a[p]])getVis(p+a[p]);
        if(inside(p+b[p]) && !vis[p+b[p]])getVis(p+b[p]);
    }

    inline void init(){
        qread(N);infty=false;tail=0;
        rep(i,1,N)qread(a[i]);
        rep(i,1,N)qread(b[i]),pre[i]=0;
    }
public:
    inline void launch(){
        init();
        getVis(1);
        if(!vis[N])exit(puts("No solution!")&0);
        rep(i,1,N)vis[i]=false;
        dfs(1);
        puts("Infinity!");
    }
}This;

signed main(){
#ifdef FILEOI
    freopen("file.in","r",stdin);
    freopen("file.out","w",stdout);
#endif
    This.launch();
    return 0;
}

思路分析及正解代码

要说这道题有什么思路,还真的是一通乱搞。

首先,确定无解的情况:

inline bool inside(const int p){
    return 0<p && p<=N;
}
inline void getMark(const int p){
    vis[p]=true;
    if(p==N){
        path[p]=true;
        return;
    }
    if(inside(p+a[p])){
        if(!vis[p+a[p]])getMark(p+a[p]);
        if(path[p+a[p]])path[p]=true;
    }
    if(inside(p+b[p])){
        if(!vis[p+b[p]])getMark(p+b[p]);
        if(path[p+b[p]])path[p]=true;
    }
}

其中,这个 vis 记录这个点有没有被访问过,而 path 记录是否能从这个点到终点。

那么,如果 path[1]==1 ,那么可以直接输出 No solution!

否则,我们就开始第二次 dfs ,且看下面这片代码:

inline void dfs(const int p){
    vis[p]=true;
    if(p==N)exit(putAns()&0);
    if(inside(p+a[p]) && path[p+a[p]]){
        if(vis[p+a[p]])exit(puts("Infinity!")&0);
        st[++tail]='a';
        dfs(p+a[p]);
        --tail;
    }
    if(inside(p+b[p]) && path[p+b[p]]){
        if(vis[p+b[p]])exit(puts("Infinity!")&0);
        st[++tail]='b';
        dfs(p+b[p]);
        --tail;
    }
}

请注意,第二次 dfs 的时候,是按照我们第一次打标时所标记的路径 path 数组进行 dfs 的。

我们是按照优先级来搜索的,所以如果搜到一个自环时,是可以保证这个无限的自环是最优的,直接输出 Infinity! 即可。

否则,如果我们到了终点 \(N\) ,输出栈里面的字符串即可。

完整代码

#include<cstdio>
#include<cstdlib>

#define rep(i,__l,__r) for(int i=__l,i##_end_=__r;i<=i##_end_;++i)
#define fep(i,__l,__r) for(int i=__l,i##_end_=__r;i>=i##_end_;--i)
#define writc(a,b) fwrit(a),putchar(b)
#define mp(a,b) make_pair(a,b)
#define ft first
#define sd second
#define LL long long
#define ull unsigned long long
#define pii pair<int,int>
#define Endl putchar('\n')
// #define FILEOI
// #define int long long

#ifdef FILEOI
    #define MAXBUFFERSIZE 500000
    inline char fgetc(){
        static char buf[MAXBUFFERSIZE+5],*p1=buf,*p2=buf;
        return p1==p2&&(p2=(p1=buf)+fread(buf,1,MAXBUFFERSIZE,stdin),p1==p2)?EOF:*p1++;
    }
    #undef MAXBUFFERSIZE
    #define cg (c=fgetc())
#else
    #define cg (c=getchar())
#endif
template<class T>inline void qread(T& x){
    char c;bool f=0;
    while(cg<'0'||'9'<c)f|=(c=='-');
    for(x=(c^48);'0'<=cg&&c<='9';x=(x<<1)+(x<<3)+(c^48));
    if(f)x=-x;
}
inline int qread(){
    int x=0;char c;bool f=0;
    while(cg<'0'||'9'<c)f|=(c=='-');
    for(x=(c^48);'0'<=cg&&c<='9';x=(x<<1)+(x<<3)+(c^48));
    return f?-x:x;
}
template<class T,class... Args>inline void qread(T& x,Args&... args){qread(x),qread(args...);}
template<class T>inline T Max(const T x,const T y){return x>y?x:y;}
template<class T>inline T Min(const T x,const T y){return x<y?x:y;}
template<class T>inline T fab(const T x){return x>0?x:-x;}
inline int gcd(const int a,const int b){return b?gcd(b,a%b):a;}
inline void getInv(int inv[],const int lim,const int MOD){
    inv[0]=inv[1]=1;for(int i=2;i<=lim;++i)inv[i]=1ll*inv[MOD%i]*(MOD-MOD/i)%MOD;
}
template<class T>void fwrit(const T x){
    if(x<0)return (void)(putchar('-'),fwrit(-x));
    if(x>9)fwrit(x/10);putchar(x%10^48);
}
inline LL mulMod(const LL a,const LL b,const LL mod){//long long multiplie_mod
    return ((a*b-(LL)((long double)a/mod*b+1e-8)*mod)%mod+mod)%mod;
}

const int MAXN=1e5;

class task{
private:
    int N,tail;
    int a[MAXN+5],b[MAXN+5];
    bool infty,vis[MAXN+5],path[MAXN+5];
    char st[MAXN<<4];

    inline bool inside(const int p){
        return 0<p && p<=N;
    }

    inline bool putAns(){
        if(tail<1)return false;
        rep(i,1,tail)putchar(st[i]);
        return true;
    }

    inline void init(){
        qread(N);tail=0;
        rep(i,1,N)qread(a[i]);
        rep(i,1,N)qread(b[i]);
    }

    inline void getMark(const int p){
        vis[p]=true;
        if(p==N){
            path[p]=true;
            return;
        }
        if(inside(p+a[p])){
            if(!vis[p+a[p]])getMark(p+a[p]);
            if(path[p+a[p]])path[p]=true;
        }
        if(inside(p+b[p])){
            if(!vis[p+b[p]])getMark(p+b[p]);
            if(path[p+b[p]])path[p]=true;
        }
    }

    inline void dfs(const int p){
        vis[p]=true;
        if(p==N)exit(putAns()&0);
        if(inside(p+a[p]) && path[p+a[p]]){
            if(vis[p+a[p]])exit(puts("Infinity!")&0);
            st[++tail]='a';
            dfs(p+a[p]);
            --tail;
        }
        if(inside(p+b[p]) && path[p+b[p]]){
            if(vis[p+b[p]])exit(puts("Infinity!")&0);
            st[++tail]='b';
            dfs(p+b[p]);
            --tail;
        }
    }
public:
    inline void launch(){
        init();
        getMark(1);
        if(!path[1])exit(puts("No solution!")&0);
        rep(i,1,N)vis[i]=false;
        dfs(1);
    }
}This;

signed main(){
#ifdef FILEOI
    freopen("file.in","r",stdin);
    freopen("file.out","w",stdout);
#endif
    This.launch();
    return 0;
}

水完了一篇题解了...

「题解」「美团 CodeM 资格赛」跳格子

标签:ati   开始   signed   出栈   getc   lib   cpp   sign   span   

原文地址:https://www.cnblogs.com/MachineryCountry/p/12039106.html

(0)
(0)
   
举报
评论 一句话评论(0
登录后才能评论!
© 2014 mamicode.com 版权所有  联系我们:gaon5@hotmail.com
迷上了代码!