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
原创粉丝点击