实验室(搜索->记忆化搜索->动规优化)
實驗室
題目描述:
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;
}
總結
以上是生活随笔為你收集整理的实验室(搜索->记忆化搜索->动规优化)的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: element-ui Tree之懒加载叶
- 下一篇: FLASH绘制三角形方法