• 【3001】均分纸牌


    Time Limit: 2second
    Memory Limit: 2 MB

    有n堆纸牌,编号分别为1,2....n。每堆上有若干张,但纸牌总数必为n的倍数。可以在任一堆上取若干张纸牌,然后移动。
    移动规则为:在编号为1堆上取的纸牌,只能移到编号为2的堆上;在编号为n堆上取的纸牌,只能移到编号为n-1的堆上;其他堆上取的纸牌,可以移动到相邻左边或者右边的堆上。
    现在要求找出一种移动方法,用最少的移动次数使每堆上的纸牌数都一样多。
    例如n=4,4堆纸牌数分别为①9 ②8 ③17 ④6
    移动3次可达到目的:
    从③取4张纸牌放到④(9 8 13 10)
    从③取4张纸牌放到②(9 11 10 10)
    从②取4张纸牌放到①(10 10 10 10)

    Input

    输入文件两行。
    第一行输入n(1≤n≤100)。
    第二行输入a1 a2 .... an(每堆纸牌初始数,1≤ai≤10000)

    Output

    所有堆均达到相等的最少移动次数(最后用换行结束)

    Sample Input

    4
    9 8 17 6
    

    Sample Output

    3
    

    【题解】

    这题要特别注意一点,“其他堆上取的纸牌,可以移动到相邻左边或者右边的堆上。”,即只能移到相邻的牌堆上。知道这一点后我们可以先考虑第一堆。

    先求出平均数ave,如果第一堆牌数小于ave,只能从第二堆拿所需要的,让第一堆数目到ave。接下来第二堆,如果再从第一堆拿牌到第二堆,显然是不划算的,只能从第3堆拿或者第二堆多了 拿到第3堆去(还是要强调,题目要求只能从相邻牌堆拿),这样一直下去,到了第n-1堆,前N-1堆排好了,第n堆自然也就排好了,因为是n的倍数。

    【代码】

    #include <cstdio>
    
    int a[150],n,ans = 0;
    
    void input_data()
    {
        scanf("%d",&n);
        for (int i = 1;i <= n;i++)
            scanf("%d",&a[i]);
    }
    
    void get_ans()
    {
        int ave = 0;
        for (int i = 1;i <= n;i++)
            ave += a[i];
        ave /= n; //先算出平均数
        for (int i = 1;i <= n-1;i++) //开始移动
            {
                if (a[i] != ave) ans++; //如果第i堆不是等于平均数,则一定要移,那么就增加操作数
                a[i+1] = a[i+1] + a[i] - ave; //直接增加第i+1堆 a[i] - ave ,负数则变成减的
                a[i] = ave; //a[i]一定可以变成ave。
            }
    }
    
    void output_ans()
    {
        printf("%d
    ",ans);
    }
    
    int main()
    {
        input_data();
        get_ans();
        output_ans();
        return 0;
    }
    



     

  • 相关阅读:
    【一天一道兼容性】之——IE6下fixed失效
    【前端重构技能天赋】(三)——最终篇
    Putty中文乱码问题
    Cygwin Application initialization failed: no display name and no $DISPLAY environment
    c++中的string用法(二)
    在win7下面使用cygwin,并且安装使用git,以及git简明教程
    vi 一些命令(备忘,自己用的)
    对C++中string类型的总结
    ofstream和ifstream详细用法
    写第一个shell脚本,遇到的问题总结整理。
  • 原文地址:https://www.cnblogs.com/AWCXV/p/7632456.html
Copyright © 2020-2023  润新知