题意:
给n长度的数组,a1,a2,a3,a4,a5…an,他可以实现跳跃从 ai 跳到a(i-ai)或者a(i+ai)这其中i-ai>=1 i+ai<=n
问如果他跳跃到的地方与他ai值的奇偶不同,就停止跳跃,比如 1 2 3,a1->a(1+1)=2就停止了,a2->a(2+2or2-2)都不符合所以没有跳,输出-1
其中跳不了和跳不到与ai奇偶不同的地方就输出-1
问每个位置需要最少跳几次。
思路
搜索,怎么搜呢,先找到一步就能跳到的点,ai%2!=aj%2同时i+ai==j或者i-ai==j这种。
然后这里就是看别人大佬的思路了,思路贼清晰,建一个ai%2==aj%2 && i+ai==j或者i-ai==j
前者建边是ai+i->i 后者是i-ai->i 的。为什么这样呢,这是从 一步就跳到的点 开始广搜。从最小步数往大步数搜。如果这个点之前没搜到过的点,就是bu+1,然后存进去
#include <bits/stdc++.h> using namespace std; #define ll long long #define ull unsigned long long #define il inline #define it register int #define inf 0x3f3f3f3f #define lowbit(x) (x)&(-x) #define pii pair<int,int> #define mak(n,m) make_pair(n,m) #define mem(a,b) memset(a,b,sizeof(a)) #define mod 998244353 const int maxn=2e5+10; struct node{ int v,next; }a[maxn<<1]; int cnt,head[maxn],n,m,t,aa[maxn]; il void add(int u,int v){ a[cnt].v=v;a[cnt].next=head[u]; head[u]=cnt++; } int bu[maxn]; queue<int>q; int main(){ mem(head,-1);mem(bu,-1); scanf("%d",&n); for(it i=1;i<=n;i++){ scanf("%d",&aa[i]); } for(it i=1;i<=n;i++){ if(i-aa[i]>0 && aa[i]%2==aa[i-aa[i]]%2){ add(i-aa[i],i); } if(i+aa[i]<=n && aa[i]%2==aa[i+aa[i]]%2){ add(i+aa[i],i); } } for(it i=1;i<=n;i++){ if(i-aa[i]>0 && aa[i]%2!=aa[i-aa[i]]%2 || i+aa[i]<=n && aa[i]%2!=aa[i+aa[i]]%2){ bu[i]=1;q.push(i); } } while(!q.empty()){ int u=q.front();q.pop(); for(it i=head[u];~i;i=a[i].next){ int v=a[i].v; if(bu[v]==-1 || bu[v]>bu[u]+1){ bu[v]=bu[u]+1;q.push(v); } } } for(it i=1;i<=n;i++){ printf(i==n?"%d ":"%d ",bu[i]); } return 0; }
感觉思路好清晰,把它直接转换为图来搜,这种想法受教了