454. 帮帮小叮当
时间限制 5000 ms
内存限制 65536 KB
题目描述
小叮当刚刚学会了传送门的使用方法,可是它不小心跌落到二维空间一个 n * m 的矩阵格子世界的入口(1,1)处,
他得知出口在(n,m)处,每穿越一个格子门,它的体力值会下降。
又饿又累的他 IQ 已经降为负数了,聪明的你,能帮他规划一下路线,使得它体力值下降的最少吗?
每一行有且仅有一个传送门,但是小叮当上课睡着了,只学会了用传送门瞬移到相邻行的另一个传送门且耗 1 滴体力。
此外,他就只能通过格子门走到相邻四个格子中的一个,也耗 1 滴体力。
ps,由于符合的路径太多了,你只需要告诉我们体力值消耗最小值。
输入格式
每组数据,第一行给 n,m 两个整数(2 <= n,m <= 10000),接下来一行,有 n 个数字,代表该行传送门的位置 x( 1 <= x <= m )。以 n,m 都为0结束。Mays温馨提醒:数据组数略大于100。
输出格式
对每组输入,输出一行,体力消耗最小值。
输入样例
5 5
5 4 3 2 1
0 0
输出样例
8
最短路问题,建图姿势很重要。该题,起点到各传送门,各传送门到终点,各个传送门之间,建图。由于是稀疏图,用SPFA做。
注意:用vector时记得clear,不然会出错。(相当于数组初始化)。
代码:#include<iostream> #include<cstdio> #include<cstdlib> #include<algorithm> #include<cmath> #include<cstring> #include<queue> #include<stack> using namespace std; struct edge { int to,cost; }; vector <edge> g[10010]; queue <int> p; bool inp[10010]; int a[10010],d[10010]; int main() { int n,m,i,sz; edge q; while(scanf("%d %d",&n,&m)&&n&&m) { for(i=0;i<=n+1;i++) g[i].clear(); for(i=1;i<=n;i++) { scanf("%d",&a[i]); q.to=i; q.cost=a[i]+i-2; g[0].push_back(q); q.cost=m+n-a[i]-i; q.to=n+1; g[i].push_back(q); } for(i=1;i<n;i++) { q.to=i+1; q.cost=1; g[i].push_back(q); q.to=i; g[i+1].push_back(q); } memset(inp,0,sizeof(bool)*(n+2)); for(i=0;i<=n+1;i++) d[i]=(i==0?0:20000); p.push(0); while(!p.empty()) { int x=p.front(); p.pop(); inp[x]=false; for(i=0,sz=g[x].size();i<sz;i++) { if(d[g[x][i].to]>d[x]+g[x][i].cost) { d[g[x][i].to]=d[x]+g[x][i].cost; if(!inp[g[x][i].to]) { inp[g[x][i].to]=true; p.push(g[x][i].to); } } } } printf("%d\n",d[n+1]); } return 0; }