贪心算法(二)

在这里记录一个比较典型的贪心算法题目。

题目描述:现有n堆纸牌,编号分别为1,2,3,…,n。可以在任一堆上取若干张纸牌,然后移动。

                 移牌规则:第一堆的牌只能移到第二堆,第n堆只能移到第(n-1)堆,其余编号的牌可以移到左右相邻的堆数里。

                 现在要求找出一种移动方法,用最少的移动次数使每堆上纸牌数都一样多。

输入格式:

键盘输入文件名。文件格式:

N(N 堆纸牌,1 <= N <= 100)

A1 A2 … An (N 堆纸牌,每堆纸牌初始数,l<= Ai <=10000)

输出格式:

输出至屏幕。格式为:

所有堆均达到相等时的最少移动次数。

输入输出样例

输入样例#1:
4
9 8 17 6
输出样例#1:



算法分析:这道题目的关键是找到平均值这个突破点。就拿样例来说,四堆牌的平均值为10,用每一堆的牌数减去平均值就得到-1,-2,7,-4。这样题目就转化为怎样移动使得每堆牌的数值都为0。即每一堆不为零的值都传给右边相邻的一堆,直到每堆牌对应的值都为0为止。如:-1传给-2就得到(0,-3,7,-4);-3传给7就得到(0,0,4,-4);-4传给4就得到(0,0,0,0)。即一共移动三次就达到了题目的要求,此时移动次数最少。

算法实现基本思路:求出n堆纸牌的平均值,定义两个指针i和j,分别从两侧逐一过滤。

#include<bits/stdc++.h>
using namespace std;
int a[100001];
int main()
{
    int n,ave=0,step=0,i,j;
    cin>>n;
    for(i=1;i<=n;i++)
    {
        cin>>a[i];
        ave+=a[i];//计算总数
    }
    ave/=n;//算出平均值
    for(i=1;i<=n;i++) a[i]-=ave;
    i=1;j=n;//定义两个指针
    while(a[i]==0&&i<n) i++;//筛掉左边的0
    while(a[j]==0&&j>1) j--;//筛掉右边的0
    while(i<j)
    {
        a[i+1]+=a[i];//将第i堆牌移到第(i+1)堆中去
        a[i]=0;//第i堆牌移走后变为0
        step++;//移动步数+1
        i++;//对下一堆牌进行循环操作
        while(a[i]==0&&i<j) i++;//过滤移牌过程中产生的0
    }
    cout<<step<<endl;
    return 0;
}

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值