Gym
来源:互联网 发布:怎么用美工刀削铅笔 编辑:程序博客网 时间:2024/06/03 05:10
题目链接:http://codeforces.com/gym/101147/problem/E
题意:当人在第i个商店时,他可以向左或向右跳di段距离到达另一个商店(在范围之内),一个商店为一段距离。问:对于每一个商店,跳到最后一个商店最少需要跳几次?
题解:题目实际上是求最短距离,而且边权为1,所以可以直接用bfs。由于是求每个点到最后一个点的最短距离,那么可以反向建图,将最后一个点设为起始点,然后向前跑。对于跑不到的点,回到题目上说,实际就是这个商店不能到达最后一个商店。
代码如下:
#include <iostream>#include <cstdio>#include <cstring>#include <cstdlib>#include <string>#include <vector>#include <map>#include <set>#include <queue>#include <sstream>#include <algorithm>using namespace std;#define pb push_back#define mp make_pair#define ms(a, b) memset((a), (b), sizeof(a))//#define LOCAL#define eps 0.0000001typedef long long LL;const int inf = 0x3f3f3f3f;const int maxn = 100000+10;const int mod = 1000000007;vector <int > v[maxn];LL len[maxn];struct node{ int sta; LL k;};queue<node>q;node now, e;int vis[maxn];int bfs(int be){ ms(vis,0); while(!q.empty()) q.pop(); now.sta = be; now.k = 0; vis[be] = 1; q.push(now); len[be] = 0; while(!q.empty()) { now = q.front(); q.pop(); int big = v[now.sta].size(); for(int i = 0; i<big; i++) { if(!vis[ v[now.sta][i] ]) { e.sta = v[now.sta][i] ; e.k = now.k+1; len[e.sta] = e.k; vis[e.sta ] = 1; q.push(e); } } } return 0;}void solve(){ int n; scanf("%d", &n); for(int i = 1; i<=n; i++) v[i].clear(); for(int i=1;i<=n;i++) { int d; scanf("%d", &d); if(i-d>=1) v[i-d].pb(i);//反向建图 if(i+d<=n) v[i+d].pb(i); } ms(len,-1); bfs(n); for(int i = 1; i<=n; i++) printf("%lld\n",len[i]);}int main(){ #ifdef LOCAL freopen("jumping.in", "r", stdin);// freopen("output.txt", "w", stdout); #endif // LOCAL int T; scanf("%d", &T); while(T--){ solve(); } return 0;}
0 0