日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問 生活随笔!

生活随笔

當前位置: 首頁 > 编程资源 > 综合教程 >内容正文

综合教程

实验室(搜索->记忆化搜索->动规优化)

發布時間:2023/12/19 综合教程 28 生活家
生活随笔 收集整理的這篇文章主要介紹了 实验室(搜索->记忆化搜索->动规优化) 小編覺得挺不錯的,現在分享給大家,幫大家做個參考.

實驗室

題目描述:
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]<a href="http://t.zoukankan.com/abs%28j-l%29l
本來應該循環但超時
令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;
}

總結

以上是生活随笔為你收集整理的实验室(搜索-&gt;记忆化搜索-&gt;动规优化)的全部內容,希望文章能夠幫你解決所遇到的問題。

如果覺得生活随笔網站內容還不錯,歡迎將生活随笔推薦給好友。