码迷,mamicode.com
首页 > 其他好文 > 详细

CodeForces 558 C. Amr and Chemistry && 51NOD 1483 化学变换(暴力 + 贪心)

时间:2016-07-15 20:54:01      阅读:467      评论:0      收藏:0      [点我收藏+]

标签:

传送门
Amr loves Chemistry, and specially doing experiments. He is preparing for a new interesting experiment.

Amr has n different types of chemicals. Each chemical i has an initial volume of ai liters. For this experiment, Amr has to mix all the chemicals together, but all the chemicals volumes must be equal first. So his task is to make all the chemicals volumes equal.

To do this, Amr can do two different kind of operations.

Choose some chemical i and double its current volume so the new volume will be 2ai
Choose some chemical i and divide its volume by two (integer division) so the new volume will be
Suppose that each chemical is contained in a vessel of infinite volume. Now Amr wonders what is the minimum number of operations required to make all the chemicals volumes equal?

Input
The first line contains one number n (1?≤?n?≤?105), the number of chemicals.

The second line contains n space separated integers ai (1?≤?ai?≤?105), representing the initial volume of the i-th chemical in liters.

Output
Output one integer the minimum number of operations required to make all the chemicals volumes equal.

Examples
input
3
4 8 2
output
2
input
3
3 5 6
output
5
Note
In the first sample test, the optimal solution is to divide the second chemical volume by two, and multiply the third chemical volume by two to make all the volumes equal 4.

In the second sample test, the optimal solution is to divide the first chemical volume by two, and divide the second and the third chemical volumes by two twice to make all the volumes equal 1.

题目大意:
有n种不同的化学试剂。第i种有ai升。每次实验都要把所有的化学试剂混在一起,但是这些试剂的量一定要相等。所以现在的首要任务是把这些化学试剂的量弄成相等。
有两种操作:
· 把第i种的量翻倍,即第i种的量变成2ai。
· 把第i种的量减半,除的时候向下取整,即把第i种的量变成 ? ai/2 ? 。
现在所有的化学试剂的量已知,问最少要变换多少次,这些化学试剂的量才会相等。
样例解释:把8变成4,把2变成4。这样就需要两次就可以了。

解题思路:
我们可以进行一次初始化,也就是枚举出每个数能够到达的数字并且记录到达该数字需要的步数,然后从到达次数为 n 次的数字中选择步数最小的就是我们所要求的。因为我们可以通过乘以2或者除以2来得到我们想要得到的数,如果是奇数的话就得先除以2,然后一直乘以2直到达到最大值。用两个数组分别记录,vis[]记录由几个数转化而来,step[]记录这个数由多少卟转化而来,最后找到vis[i]==n 的值,然后取step[]最小的值输出即可。

My Code:

#include <iostream>
#include <cstdio>
#include <algorithm>
#include <cstring>
using namespace std;
const int MAXN = 1e6+5;
const int INF = 0x3f3f3f3f;
int step[MAXN], vis[MAXN], Max;
void Init(int x)
{
    int tmp1 = x, tmp2 = x, tmp3 = 0;
    int step1 = 0, step2 = 0, step3 = 0;
    while(1)
    {
        if(tmp1 > Max)
            break;
        tmp1<<=1;
        vis[tmp1]++;
        step1++;
        step[tmp1] += step1;
    }
    while(tmp2)
    {
        if(tmp2&1 && tmp2!=1)
        {
            tmp2>>=1;
            vis[tmp2]++;
            step2++;
            step[tmp2] += step2;
            tmp3 = tmp2;
            step3 = step2;
            while(1)
            {
                if(tmp3 > Max)
                    break;
                tmp3<<=1;
                vis[tmp3]++;
                step3++;
                step[tmp3] += step3;
            }
        }
        else
        {
            tmp2>>=1;
            vis[tmp2]++;
            step2++;
            step[tmp2] += step2;
        }
    }
}
int a[MAXN];
int main()
{
    int n;
    while(~scanf("%d",&n))
    {
        Max = -1;
        memset(vis, 0, sizeof(vis));
        memset(step, 0, sizeof(step));
        for(int i=0; i<n; i++)
        {
            scanf("%d",&a[i]);
            vis[a[i]] = 1;
            if(Max < a[i])
                Max = a[i];
        }
        for(int i=0; i<n; i++)
            Init(a[i]);
        int ans = INF;
        for(int i=1; i<=Max*2; i++)
        {
            if(vis[i] == n)
            {
                if(step[i] < ans)
                    ans = step[i];
            }
        }
        printf("%d\n",ans);
    }
    return 0;
}

CodeForces 558 C. Amr and Chemistry && 51NOD 1483 化学变换(暴力 + 贪心)

标签:

原文地址:http://blog.csdn.net/qingshui23/article/details/51918950

(0)
(0)
   
举报
评论 一句话评论(0
登录后才能评论!
© 2014 mamicode.com 版权所有  联系我们:gaon5@hotmail.com
迷上了代码!