zoukankan      html  css  js  c++  java
  • P1135 奇怪的电梯 题解

    CSDN同步

    原题链接

    简要题意:

    给定 (a_i),求从 (A) 节点走到 (B) 节点的最小步数。若当前在 (i) 节点,则可以一步到达 (i-a_i)(i+a_i) 节点。(如果不合法则不走)

    首先这题肯定是搜索,具体怎么搜因人而异。

    因为我比较喜欢朴素的 ( exttt{dfs}),因此就说说做法。

    显然,如果你打下一个这样的搜索:

    inline void dfs(int dep,int bs) {
    	if(dep<1 || dep>n) return;
    	if(bs==B) {ans=min(ans,bs);return;}
    	dfs(dep+a[dep],bs+1);
    	dfs(dep-a[dep],bs+1);
    } 
    

    你觉得没有任何问题,但是交上去 ( exttt{TLE}) 了。

    给出一组数据 ( ext{hack}) 掉它:

    5 3 4
    2 1 2 1 2
    

    然后你的程序彻底陷入死循环了。。。

    然后,你机智地说:好,那么我记录上一次的位置,就可以避免重复了!

    inline void dfs(int dep,int bs,int last) {
    	if(dep<1 || dep>n) 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);
    } 
    

    好,交上去还是 ( exttt{TLE}) 了。

    再送你一组数据强力 ( ext{hack})

    5 1 5
    1 2 1 3 1
    

    然后你的程序就是这样的:

    (1 ightarrow 2 ightarrow 4 ightarrow1 ightarrow2 ightarrow4 ightarrow cdots)

    仍然不行了。

    那你说,好,我用一个桶记录走过的步数,不重复走。

    然后交上去 ( exttt{WA}) 了。再送你两组 ( ext{hack}) 数据:

    假设你的程序优先往下走:

    5 3 5
    4 1 2 1 2
    

    然后你用 (2) 步走到终点,发现 (1,3,5) 都走过了,然后咕了。

    如果优先向上走:

    5 3 1
    2 1 2 1 4
    

    这不一样的道理?

    那你说,这怎么办?

    我:显然记忆化答案!

    (f_i) 表示 当前 走到第 (i) 层的最少步数。

    如果当前步数 (geq f_i) 就可以直接停止。

    再做一遍即可。

    时间复杂度:(O(n)).

    实际得分:(90pts).

    #pragma GCC optimize(2)
    #include<bits/stdc++.h>
    using namespace std;
    
    inline int read(){char ch=getchar();int f=1;while(ch<'0' || 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(dep<1 || dep>n) 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
    ",f[B]); //直接走
    	return 0;
    }
    
    

    没有一点点的问题啊? 其实我自己也中了这个坑

    那么,最后送你组 ( ext{hack}) 数据:

    5 1 1
    0 0 0 0 0
    

    你的程序输出了 (1),所以 (A=B) 的直接处理掉!

    实际得分:(100pts).

    #pragma GCC optimize(2)
    #include<bits/stdc++.h>
    using namespace std;
    
    inline int read(){char ch=getchar();int f=1;while(ch<'0' || 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(dep<1 || dep>n) 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
    ",f[B]);
    	return 0;
    }
    
    
  • 相关阅读:
    【原创】【JNI】OPUS压缩与解压的JNI调用(.DLL版本)
    线性基学习笔记
    杜教筛&Min_25筛学习笔记
    LOJ2540 随机算法
    仙人掌&圆方树学习笔记
    CF487E Tourists
    BZOJ2125 最短路
    [SHOI2008]仙人掌图
    BZOJ4316 小C的独立集
    NOI2015 品酒大会
  • 原文地址:https://www.cnblogs.com/bifanwen/p/12600066.html
Copyright © 2011-2022 走看看