題目連結:http://acm.hdu.edu.cn/showproblem.php?pid=1548
題目大意:就是說有一個很奇怪的升降機,它有兩個按鈕UP和DOWN,給你一些數i展示層數,並且每層對應的Ki,如果按UP按鈕,會從第i層升到第i+Ki層;如果按了DOWN則會從第i層降到第i-Ki層;並規定能到的層數為1到N,根據常識也知道。現在的要求就是給你N,A,B和一串數K1到Kn,問你從A到B,至少按幾下按鈕。
解法有多種:
解法一:最短路求解:
代碼:
#include<iostream>using namespace std;#define INF 100000000int map[205][205];int dist[205],S[205];int N,A,B;int Dijkstra(int u,int v){ memset(S,0,sizeof(S)); int i,j,k; for(i=1;i<=N;i++) { dist[i]=map[u][i]; } S[u]=1; dist[u]=0; for(i=1;i<N;i++) { int min=INF,t; for(j=1;j<=N;j++) { if(!S[j]&&dist[j]<min) { t=j; min=dist[j]; } } if(min==INF)//說明不存在從A到B的任何路徑 return -1; if(t==v)//已到達B return min; S[t]=1; for(k=1;k<=N;k++) { if(!S[k]&&dist[t]+map[t][k]<dist[k]) dist[k]=dist[t]+map[t][k]; } } return -1;}int main(){ int i,j,c; while(cin>>N,N) { cin>>A>>B; for(i=1;i<=N;i++) { for(j=1;j<=N;j++) map[i][j]=i==j?0:INF; } for(i=1;i<=N;i++) { cin>>c; if(i+c<=N) map[i][i+c]=1; if(i-c>=1) map[i][i-c]=1; } if(A==B)//如果坑爹的題目問你從i到i就坑死了 { cout<<"0"<<endl; } else cout<<Dijkstra(A,B)<<endl; } return 0;}
第二種解法:廣搜
代碼:
#include<iostream>using namespace std;#include<queue>int n;struct node{ int c; int num;}m,n1,n2,t;queue<node> Q;int main(){ int a,b,c[205],s; bool map[205],flag; int i; while(~scanf("%d",&n),n) { scanf("%d%d",&a,&b); for(i=1;i<=n;i++) { scanf("%d",&c[i]); map[i]=false; } if(a==b) { printf("0\n"); continue; } m.c=a; m.num=0; Q.push(m); map[m.c]=true; flag=false; while(!Q.empty()) { t=Q.front(); Q.pop(); if(t.c==b) { flag=true; s=t.num; break; } n1.c=t.c+c[t.c]; if(n1.c>=1&&n1.c<=n&&!map[n1.c]) { n1.num=t.num+1; Q.push(n1); map[n1.c]=true; } n2.c=t.c-c[t.c]; if(n2.c>=1&&n2.c<=n&&!map[n2.c]) { n2.num=t.num+1; Q.push(n2); map[n2.c]=true; } } if(flag==true) printf("%d\n",s); else printf("-1\n"); while(!Q.empty()) Q.pop(); } return 0;}
注意如果沒有給你走的的層數標記的話,在一種極端的情況下會在i和j層不斷地走從而導致的就是超記憶體,被它卡了5次超記憶體;沒能徹底理解它,真差