loj 6084.「美团 CodeM 资格赛」跳格子

题目:

link

题解:

尽量走\(a\).
只要保证走\(a\)后到达的点一定可以到终点就可以走。
所以从终点开始\(dfs\)出所有能够到达终点的点。
然后再从起点开始\(dfs\)路径即可。
如果\(dfs\)出环代表字符串无现长。

#include <vector>
#include <cstdio>
#include <cstring>
#include <algorithm>
using namespace std;
typedef long long ll;
inline void read(int &x){
    x=0;static char ch;static bool flag;flag = false;
    while(ch=getchar(),ch<'!');if(ch == '-') ch=getchar(),flag = true;
    while(x=10*x+ch-'0',ch=getchar(),ch>'!');if(flag) x=-x;
}
#define rg register int
#define rep(i,a,b) for(rg i=(a);i<=(b);++i)
#define per(i,a,b) for(rg i=(a);i>=(b);--i)
const int maxn = 100010;
int a[maxn],b[maxn],n,len;
bool vis[maxn],vt[maxn];
char s[maxn<<1];
vector<int>ve[maxn];
void check(int u){
    if(vt[u]) return ;
    vt[u] = true;
    for(vector<int>::iterator it = ve[u].begin();it != ve[u].end();++ it){
        check(*it);
    }
}
bool dfs(int u,int i){
    if(u == n){len = i;return true;}
    if(vis[u]) return false;
    vis[u] = true;
    if(1 <= u + a[u] && u + a[u] <= n && vt[u + a[u]]){
        if(dfs(u + a[u],i + 1) == false) return false;
        s[i] = 'a';return true;
    }
    if(1 <= u + b[u] && u + b[u] <= n && vt[u + b[u]]){
        if(dfs(u + b[u],i + 1) == false) return false;
        s[i] = 'b';return true;
    }
}
int main(){
    read(n);
    rep(i,1,n){
        read(a[i]);
        if(1 <= i + a[i] && i + a[i] <= n) ve[i+a[i]].push_back(i);
    }
    rep(i,1,n){
        read(b[i]);
        if(1 <= i + b[i] && i + b[i] <= n) ve[i+b[i]].push_back(i);
    }
    check(n);
    if(vt[1] == 0) puts("No solution!");
    else{
        if(dfs(1,0) == false) puts("Infinity!");
        else s[len] = 0,printf("%s",s);
    }
    return 0;
}
posted @ 2017-06-25 19:24  Sky_miner  阅读(482)  评论(0编辑  收藏  举报