Amr and Chemistry CodeForces 558C(BFS)

http://codeforces.com/problemset/problem/558/C

分析:将每一个数在给定范围内(10^5)可变成的数(*2或者/2)都按照广搜的方式生成访问一遍,标记上访问的步数,之后遍历区间找到被访问次数达到n(所有数都可以变成这个数)并且标记的需要步数最少即可。

注意:当是奇数的时候,例如11(11/2=5 5*2=10),按照这么算(除2后再乘2)回重新得到一个新的数

#include <cstdio>
#include <cstring>
#include <iostream>
#include <cmath>
#include<vector>
#include<queue>
#include<algorithm>

using namespace std;
typedef long long LL;

const int maxn=1000009;
const int INF=0x3f3f3f3f;
const int mod=2009;
int time[maxn], step[maxn];

void UP(int x, int steps)///统计x的偶数倍
{
    while(x<=100000)
    {
        time[x]++;
        step[x]+=steps;
        x*=2;
        steps++;
    }
}

void BFS(int x)
{
    UP(x, 0);

    int steps = 0;
    while(x)
    {
        steps++;

        if(x&1 && x>1)///统计x是奇数的情况,并且x!=1
        {
            x/=2;
            UP(x, steps);
        }
        else///统计x是偶数的情况
        {
            x/=2;
            time[x]++;
            step[x]+=steps;
        }
    }
}

int main()
{
    int n, num;

    while(scanf("%d", &n)!=EOF)
    {
        memset(time, 0, sizeof(time));///标记这个数被生成了几次
        memset(step, 0, sizeof(step));///标记生成这个数的步数

        for(int i=1; i<=n; i++)
        {
            scanf("%d", &num);

            BFS(num);
        }

        int ans = INF;
        for(int i=1; i<=100000; i++)
        {
            if(time[i] == n)///若这N个数都被标记成了i,取相对应的步数值
                ans = min(ans, step[i]);
        }

        printf("%d
", ans);
    }
    return 0;
}

/*
2
1 1
*/
View Code
原文地址:https://www.cnblogs.com/daydayupacm/p/5799429.html