题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=1548
题意:n层楼,坐电梯从a层到b层。第i层有一个数Ki,可以上到i+Ki层,可以下到i-K层。求最少几次能从a到b层。
思路:这题比较经典的做法就是bfs然后标记状态,求出最小步数。但是我想说的是用最短路写,可以到达的相邻两点的距离为1。然后用最短路就行了,我是用的spfa,据讨论区说好像有负数?
code:
bfs版
#include<cstdio>
#include<queue>
#include<cstring>
using namespace std;
struct node{int step,num;}s;
const int MAXN=200+5;
int N,A,B,k[MAXN];
bool visit[MAXN];
void bfs(){
queue<node>q;
while(!q.empty())q.pop();
memset(visit,false,sizeof(visit));
s.step=0;s.num=A;
q.push(s);
while(!q.empty()){
node ne=q.front();q.pop();
if(visit[ne.num])continue;
visit[ne.num]=true;
if(ne.num==B){printf("%d\n",ne.step);return ;}
int change=k[ne.num];
if(ne.num+change<=N){
node no=ne;
no.step++;
no.num=ne.num+change;
q.push(no);
}
if(ne.num-change>=1){
node no=ne;
no.step++;
no.num=ne.num-change;
q.push(no);
}
}
printf("-1\n");
}
int main(){
while(scanf("%d",&N)&&N&&scanf("%d%d",&A,&B)){
for(int i=1;i<=N;++i)
scanf("%d",k+i);
bfs();
}
}
最短路版:
#include<cstdio>
#include<cstring>
const int MAXV=200+5;
const int MAXE=500;
const int INF=99999999;
struct edge{int v,next,cost;}es[MAXE];
int N,A,B,tot,head[MAXV],d[MAXV],k[MAXV];
bool visit[MAXV];
void init(){
tot=0;
memset(head,-1,sizeof(head));
}
void addEdge(int a,int b,int c){
es[tot].cost=c;
es[tot].v=b;
es[tot].next=head[a];
head[a]=tot++;
}
void spfa(){
for(int i=1;i<=N;++i)
d[i]=INF,visit[i]=false;
d[A]=0;visit[A]=true;
int Q[MAXV];
int top=0;Q[top++]=A;
while(top!=0){
int no=Q[--top];
visit[no]=false;
for(int i=head[no];i!=-1;i=es[i].next){
int to=es[i].v;
if(d[to]>d[no]+es[i].cost){
d[to]=d[no]+es[i].cost;
if(!visit[to]){
visit[to]=true;
Q[top++]=to;
}
}
}
}
if(d[B]==INF)printf("-1\n");
else printf("%d\n",d[B]);
}
int main(){
while(scanf("%d",&N)&&N&&scanf("%d%d",&A,&B)){
init();//不要忘了
for(int i=1;i<=N;++i){
scanf("%d",k+i);
if(i+k[i]<=N)addEdge(i,i+k[i],1);//因为所有直接相邻的边的权为1
if(i-k[i]>=1)addEdge(i,i-k[i],1);
}
spfa();
}
}