博客园同步
原题链接
简要题意:
给定 aia_iai,求从 AAA 节点走到 BBB 节点的最小步数。若当前在 iii 节点,则可以一步到达 i−aii-a_ii−ai 或 i+aii+a_ii+ai 节点。(如果不合法则不走)
首先这题肯定是搜索,具体怎么搜因人而异。
因为我比较喜欢朴素的 dfs\texttt{dfs}dfs,因此就说说做法。
显然,如果你打下一个这样的搜索:
inline void dfs(int dep,int bs) {
if(depn) return;
if(bs==B) {ans=min(ans,bs);return;}
dfs(dep+a[dep],bs+1);
dfs(dep-a[dep],bs+1);
}
你觉得没有任何问题,但是交上去 TLE\texttt{TLE}TLE 了。
给出一组数据 hack\text{hack}hack 掉它:
5 3 4
2 1 2 1 2
然后你的程序彻底陷入死循环了。。。
然后,你机智地说:好,那么我记录上一次的位置,就可以避免重复了!
inline void dfs(int dep,int bs,int last) {
if(depn) return;
if(bs==B) {ans=min(ans,bs);return;}
if(dep+a[dep] != last) dfs(dep+a[dep],bs+1);
if(dep-a[dep] != last) dfs(dep-a[dep],bs+1);
}
好,交上去还是 TLE\texttt{TLE}TLE 了。
再送你一组数据强力 hack\text{hack}hack:
5 1 5
1 2 1 3 1
然后你的程序就是这样的:
1→2→4→1→2→4→⋯1 \rightarrow 2 \rightarrow 4 \rightarrow1 \rightarrow2 \rightarrow4 \rightarrow \cdots1→2→4→1→2→4→⋯
仍然不行了。
那你说,好,我用一个桶记录走过的步数,不重复走。
然后交上去 WA\texttt{WA}WA 了。再送你两组 hack\text{hack}hack 数据:
假设你的程序优先往下走:
5 3 5
4 1 2 1 2
然后你用 222 步走到终点,发现 1,3,51,3,51,3,5 都走过了,然后咕了。
如果优先向上走:
5 3 1
2 1 2 1 4
这不一样的道理?
那你说,这怎么办?
我:显然记忆化答案!
用 fif_ifi 表示 当前 走到第 iii 层的最少步数。
如果当前步数 ≥fi\geq f_i≥fi 就可以直接停止。
再做一遍即可。
时间复杂度:O(n)O(n)O(n).
实际得分:90pts90pts90pts.
#pragma GCC optimize(2)
#include
using namespace std;
inline int read(){char ch=getchar();int f=1;while(ch'9') {if(ch=='-') f=-f; ch=getchar();}
int x=0;while(ch>='0' && ch<='9') x=(x<<3)+(x<<1)+ch-'0',ch=getchar();return x*f;}
int n,A,B,a[201];
int f[201];
inline void dfs(int dep,int bs) {
if(depn) return;
if(f[dep] && f[dep]<=bs) return;
f[dep]=bs;
dfs(dep+a[dep],bs+1);
dfs(dep-a[dep],bs+1);
}
int main(){
n=read(),A=read(),B=read();
for(int i=1;i<=n;i++) a[i]=read();
dfs(A,0);
if(A!=B && !f[B]) puts("-1"); //走不到
else printf("%d\n",f[B]); //直接走
return 0;
}
没有一点点的问题啊? 其实我自己也中了这个坑
那么,最后送你组 hack\text{hack}hack 数据:
5 1 1
0 0 0 0 0
你的程序输出了 111,所以 A=BA=BA=B 的直接处理掉!
实际得分:100pts100pts100pts.
#pragma GCC optimize(2)
#include
using namespace std;
inline int read(){char ch=getchar();int f=1;while(ch'9') {if(ch=='-') f=-f; ch=getchar();}
int x=0;while(ch>='0' && ch<='9') x=(x<<3)+(x<<1)+ch-'0',ch=getchar();return x*f;}
int n,A,B,a[201];
int f[201];
inline void dfs(int dep,int bs) {
if(depn) return;
if(f[dep] && f[dep]<=bs) return;
f[dep]=bs;
dfs(dep+a[dep],bs+1);
dfs(dep-a[dep],bs+1);
}
int main(){
n=read(),A=read(),B=read();
if(A==B) {puts("0");return 0;}
for(int i=1;i<=n;i++) a[i]=read();
dfs(A,0);
if(!f[B]) puts("-1");
else printf("%d\n",f[B]);
return 0;
}