现在的位置: 首页 > 综合 > 正文

CODE[VS]_1098 均分纸牌问题

2018年04月28日 ⁄ 综合 ⁄ 共 1330字 ⁄ 字号 评论关闭

        思路:贪心算法

                   所谓贪心,贪得是什么?有么有做到局部的最优带来全局的最优,,

                  从左往右扫,一直让每一堆的卡片都为0,只要最开始的满足了,而且是一步一步过滤过来的,那么最终的结果定满足都是0,,,

                   (看不懂不要急,,,慢慢看分析)

                 第一步:求出每一堆纸牌的最终结果,也就是最后每一堆纸牌的张数。

                 第二步:将每一堆纸牌的数目进行更新,也就是最终值与现在值的差,可以存在负值,负值也是有意义的。

                               从头部和尾部开始,同时对每一堆进行过滤,将为0的堆去掉,重新设置开头和结尾。

                 第三步:写一个while循环来进行每堆纸牌间的移动,核心代码:s[i+1] +=s[i];s[i] = 0;ans++;i++;while( s[i] == 0 )i++;

                              切记:在移牌的过程中,一定要时时刻刻的过滤,我一开始就是没注意到这一点,WA了好多数据。。。。至于为什么要在移牌的过程中进行

                             过滤,这个大家可以假设 更新完数组后的情况为: -3 3 5 -2 ................ ,开始,-3移动到3 -> 0 0 5 -2..........  , 如果没有过滤到第二个0的话,

                             那么,i就会从第二堆开始,进行重复的工作,但是,第二堆本来就是0了,即,我们不需要再移动纸牌了,,所以,这样的话,就多算了一次。

                  

                  下来再来讲讲为什么有的堆中能出现 负数的纸牌情况,先这样想,把第i堆的-3张牌移动到第i+1堆去,是不是等价于 把i+1堆的3张牌移动到第i堆去,

             这个就类似与我们所选择的参考对象了,,有点物理的小知识了。。。。。

下面是代码:

# include<cstdio>
# include<iostream>

using namespace std;

int s[100+6];

int main(void)
{
    int n;cin>>n;
    int sum = 0;//计算这几个数字的和
    int ans = 0;//保存输出的结果
    for ( int i = 1;i <= n;i++ )
    {
        cin>>s[i];
        sum+=s[i];
    }
    int ave = sum/n;
    for ( int i = 1;i <= n;i++ )
    {
        s[i]-=ave;
    }
    int i = 1;//i从头开始
    int j = n;//j从尾开始
    while ( s[i]==0&&i<n ) i++;//从头过滤
    while ( s[j]==0&&j>0 ) j--;//从尾部开始过滤

    while ( i<j )
    {
        s[i+1]+=s[i];
        s[i] = 0;
        i++;
        ans++;
        while( s[i]==0&&i<j )i++;//移动牌的过程中开始过滤
    }

    cout<<ans<<endl;



    return 0;
}

抱歉!评论已关闭.