您的位置:首页 > 其它

P1135 奇怪的电梯

2018-02-01 14:34 204 查看
题目描述

呵呵,有一天我做了一个梦,梦见了一种很奇怪的电梯。大楼的每一层楼都可以停电梯,而且第i层楼(1<=i<=N)上有一个数字Ki(0<=Ki<=N)。电梯只有四个按钮:开,关,上,下。上下的层数等于当前楼层上的那个数字。当然,如果不能满足要求,相应的按钮就会失灵。例如:3 3 1 2 5代表了Ki(K1=3,K2=3,……),从一楼开始。在一楼,按“上”可以到4楼,按“下”是不起作用的,因为没有-2楼。那么,从A楼到B楼至少要按几次按钮呢?

输入输出格式

输入格式:

输入文件共有二行,第一行为三个用空格隔开的正整数,表示N,A,B(1≤N≤200, 1≤A,B≤N),第二行为N个用空格隔开的非负整数,表示Ki。

输出格式:

输出文件仅一行,即最少按键次数,若无法到达,则输出-1。

输入输出样例

输入样例#1: 复制

5 1 5

3 3 1 2 5

输出样例#1: 复制

3

练习练习

这里附上三种解法:

怪怪的dp

#include<bits/stdc++.h>
using namespace std;
typedef long long ll;
#define inf 999999999

int n,s,e;
int arr[1000];
int dp[1000];

int main()
{
cin>>n>>s>>e;
for(int i=1; i<=n; i++)cin>>arr[i];
dp[s]=1;
bool flag=true;
//实现不断的更新
while(flag)
{
flag=false;
for(int i=1; i<=n; i++)
{
if(dp[i])
{
int down=i-arr[i];
int up=i+arr[i];
if(down>0)
{
if(dp[down]==0||dp[down]>dp[i]+1)
{
flag=true;
dp[down]=dp[i]+1;
}
}
if(up<=n)
{
if(dp[up]==0||dp[up]>dp[i]+1)
{
flag=true;
dp[up]=dp[i]+1;
}
}
}
}
}
cout<<dp[e]-1;

return 0;
}


Spfa+链式前向星

#include<bits/stdc++.h>
using namespace std;
typedef long long ll;
#define inf 999999999
const int maxn=5000;
int n,sx,ex;

//链式前向星存图
int e[maxn],Head[maxn],Next[maxn];
int tot=0;

//spfa
int dis[maxn];
bool vis[maxn];
queue<int>que;

//存图
void init(int x,int y)
{
tot++;
e[tot]=y;
Next[tot]=Head[x];
Head[x]=tot;
}

void spfa(int k)
{
dis[k]=0;
que.push(k);
vis[k]=true;
while(!que.empty())
{
int x=que.front();
vis[x]=false;
que.pop();
for(int p=Head[x]; p; p=Next[p])
{
int y=e[p];
if(dis[y]>dis[x]+1)
{
dis[y]=dis[x]+1;
if(!vis[y])
{
vis[y]=true;
que.push(y);
}
}
}
}
}

int main()
{
fill(dis,dis+4000,inf);
cin>>n>>sx>>ex;
for(int i=1; i<=n; i++)
{
int x;
cin>>x;
if(i-x>0)init(i,i-x);
if(i+x<=n)init(i,i+x);
}
spfa(sx);
if(dis[ex]==inf)cout<<-1;
else
cout<<dis[ex];
return 0;
}


Dijkstra

#include<bits/stdc++.h>
using namespace std;
typedef long long ll;
#define inf 999999999
const int maxn=5000;
int n,a,b;
int d[maxn][maxn];
int dis[maxn];
int vis[maxn];

int main()
{
cin>>n>>a>>b;
for(int i=1; i<=n; i++)
{
for(int j=1; j<=n; j++)
d[i][j]=inf;
d[i][i]=0;
}
for(int i=1; i<=n; i++)
{
int x;
cin>>x;
if(i-x>0)d[i][i-
4000
x]=1;
if(i+x<=n)d[i][i+x]=1;
}

for(int i=1; i<=n; i++)
dis[i]=d[a][i];
for(int i=1; i<=n; i++)
{
int minn=inf;
int t;
for(int j=1; j<=n; j++)
if(vis[j]==0&&dis[j]<minn)
{
minn=dis[j];
t=j;
}
vis[t]=1;
for(int j=1; j<=n; j++)
dis[j]=min(dis[j],dis[t]+d[t][j]);
}

if(dis[b]==inf)cout<<-1;
else cout<<dis[b];
return 0;
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: