zoukankan      html  css  js  c++  java
  • 实验室(搜索->记忆化搜索->动规优化)

    实验室

    题目描述:
    LYK 在一幢大楼里,这幢大楼共有 n 层, LYK 初始时在第 a 层上。
    这幢大楼有一个秘密实验室,在第 b 层,这个实验室非常特别,对 LYK 具有约束作用,即若 LYK 当前处于 x 层,当它下一步想到达 y 层时,必须满足|x-y|<|x-b|,而且由于实验室是不对外开放的,电梯无法停留在第 b 层。
    LYK 想做一次旅行,即它想按 k 次电梯,它想知道不同的旅行方案个数有多少个。
    两个旅行方案不同当前仅当存在某一次按下电梯后停留的楼层不同。
    输入格式:
    一行 4 个数, n,a,b,k。
    输出格式:
    一个数表示答案,由于答案较大,将答案对 1000000007 取模后输出。
    输入样例 1
    5 2 4 1
    输出样例 1
    2
    输入样例 2
    5 2 4 2
    输出样例 2
    2
    输入样例 3
    5 3 4 1
    输出样例 3
    0
    数据范围:
    对于 20%的数据 n,k<=5。
    对于 40%的数据 n,k<=10。
    对于 60%的数据 n,k<=500。
    对于 90%的数据 n,k<=2000。
    对于 100%的数据 n,k<=5000。

    暴力搜索:

    #include<iostream>
    #include<cstdio>
    #include<algorithm>
    using namespace std;
    const int maxn=5010;
    const int mod=1000000007;
    int n,a,b,k,ans;
    void dfs(int x,int y)
    {
        if(x==k+1)
        {
            ans=(ans+1)%mod;
            return;
        }
        for(int i=1;i<=n;i++)
        if(abs(y-i)<abs(y-b)&&i!=y)
        dfs(x+1,i);
    }
    int main()
    {
        scanf("%d%d%d%d",&n,&a,&b,&k);
        dfs(1,a);
        printf("%d",ans);
        return 0;
    }

    记忆化搜索:

    #include<iostream>
    #include<cstdio>
    #include<algorithm>
    using namespace std;
    const int maxn=5010;
    const int mod=1000000007;
    int n,a,b,k,ans,f[maxn][maxn];
    int dfs(int x,int y)
    {
        if(x==k+1) return 1;
        for(int i=1;i<=n;i++)
        if(abs(y-i)<abs(y-b)&&i!=y)
        {
            if(f[x+1][i]) f[x][y]=f[x][y]+f[x+1][i];
            else          f[x][y]=f[x][y]+dfs(x+1,i);
        }
        return f[x][y];
    }
    int main()
    {
        scanf("%d%d%d%d",&n,&a,&b,&k);
        f[1][a]=dfs(1,a);
        printf("%d",f[1][a]);
        return 0;
    }

    O(n^3)动规+压维

    #include<iostream>
    #include<cstdio>
    #include<algorithm>
    using namespace std;
    const int maxn=5010;
    const int mod=1000000007;
    int n,a,b,k,ans,f[2][maxn];
    int main()
    {
        scanf("%d%d%d%d",&n,&a,&b,&k);
        for(int i=1;i<=n;i++)
        f[k+1&1][i]=1;
        for(int i=k;i>=1;i--)
        {
            for(int j=1;j<=n;j++)
            f[i&1][j]=0;
            for(int j=1;j<=n;j++)
              for(int l=1;l<=n;l++)
              if(abs(j-l)<abs(j-b)&&l!=j)
              f[i&1][j]=(f[i&1][j]+f[i+1&1][l])%mod;
        }
        printf("%d",f[1][a]);
        return 0;
    }

    优化动规
    思路:
    搜索–>记忆化搜索–>动规 O(n^3)–>动规 O(n^2)
    dp状态
    f[i][j]表示第i次停在j的方案数
    倒推 边界为f[k+1][j]=1(j!=b)
    因为最后可以停在除了b的所有地方
    f[i][j]+=f[i+1]l
    本来应该循环但超时
    令x=abs(j-b)
    abs(j-l)

    #include<iostream>
    #include<cstdio>
    #include<algorithm>
    using namespace std;
    const int mod=1000000007;
    const int maxn=5010;
    int n,a,b,k,ans,f[2][maxn],sum[maxn];
    int init()
    {
        int x=0,f=1;char c=getchar();
        while(c<'0'||c>'9'){if(c=='-')f=-1;c=getchar();}
        while(c>='0'&&c<='9'){x=x*10+c-'0';c=getchar();}
        return x*f;
    }
    int main()
    {
        freopen("lab.in","r",stdin);
        freopen("lab.out","w",stdout);
        n=init();a=init();b=init();k=init();
        for(int i=1;i<=n;i++)
        {
            if(i!=b)f[k+1&1][i]=1;
            sum[i]=(sum[i-1]+f[k+1&1][i])%mod;
        }
        for(int i=k;i>=1;i--)
        {
            for(int j=1;j<=n;j++)
            f[i&1][j]=0;
            for(int j=1;j<=n;j++)
            {
                if(j==b) continue;
                int cha=abs(j-b)-1;
                int l=max(0,j-cha),r=min(n,j+cha);
                if(l>r) continue;
                f[i&1][j]=((sum[r]-sum[l-1])%mod+mod)%mod;
                f[i&1][j]=((f[i&1][j]-f[i+1&1][j])%mod+mod)%mod;
            }
            for(int j=1;j<=n;j++)
            sum[j]=(sum[j-1]+f[i&1][j])%mod;
        }
        printf("%d",f[1&1][a]);
        fclose(stdin);fclose(stdin);
        return 0;
    }
    
  • 相关阅读:
    中间代码生成器-5-编译原理
    un-动物:老鼠
    un-动物:狗
    un-动物:猫
    un-动物:鹅
    un-动物:鸭子
    un-动物:鸡
    un-常见动物-动物:马
    un-常见动物-动物:骡
    un-常见动物-动物:牛
  • 原文地址:https://www.cnblogs.com/cax1165/p/6070895.html
Copyright © 2011-2022 走看看