zoukankan      html  css  js  c++  java
  • 2016级算法第五次上机-C.Bamboo和"Coco"

    1064 Bamboo和"Coco"

    分析题意

    每个亡灵至少一个花瓣,相邻的亡灵中思念值高的要获得的花瓣高(思念值相等是不需要花瓣一样多的)。主要考贪心思路,为了使得花瓣总量最少,每次比思念值更低的“邻近亡灵”的花瓣数多一就可以了

    思路

    都是先保证每个亡灵至少一个花瓣


    思路一

    直接模拟思路,同时关心左边和右边(或者说前边和后边),一次循环是不够的,比如3 2 1,修改了1号的花瓣数,再修改2号的花瓣数,此时会对一号产生影响。需要多次遍历,直到没有新的改变为止,算法为O(n^2),大的数据主要为卡掉这种暴力的思路
    大致代码如下:

     while (flag)
        {
            flag = false;
            for (int i = 0; i < n; i++)
            {
                if (i != n - 1 && ratings[i] > ratings[i + 1] && candies[i] <= candies[i + 1])
                {
                    candies[i] = candies[i + 1] + 1;
                    flag = true;
                }
                if (i > 0 && ratings[i] > ratings[i - 1] && candies[i] <= candies[i - 1])
                {
                    candies[i] = candies[i - 1] + 1;
                    flag = true;
                }
            }
        }
    

    思路二
    两遍循环,先从左到右考虑与左边的亡灵相比,再从右到左考虑与右边的亡灵相比,可以用两个数组也可以用一个数组

    两个数组,left[]和right[]分别都初始化为1,各自只考虑左边和右边。
    对于left:当前比左边思念值高时,left[i]=left[i-1]+1;
    对于right:当前比右边思念值高时,right[i]=right[i+1]+1;
    最后要同时满足左右两边的条件,所以ans[i]=max(left[i],right[i])

    代码如下:

    const int maxx = 1e6+5;
    int Left[maxx],Right[maxx];
    int thinking[maxx];
    int main()
    {
         int n,x;
        while(~scanf("%d",&n))
        {
            for(int i = 0;i<n;i++)
            {
                scanf("%d",&thinking[i]);
            }
            for(int i = 0;i<n;i++)
            {
                Left[i]=1;Right[i]=1;
            }
    
            for(int i= 1;i<n;i++)
            {
                if(thinking[i]>thinking[i-1])
                    Left[i]=Left[i-1]+1;
            }
            for(int i = n-2;i>=0;i--)
            {
                if(thinking[i]>thinking[i+1])
                    Right[i]=Right[i+1]+1;
            }
            int res = 0;
            for(int i = 0;i<n;i++)
                res += max(Left[i],Right[i]);
            printf("%d
    ",res);
        }
    
    }
    

    也可以只用一个数组,第二遍从右到左时加点条件即可,节省空间

    核心代码如下:

    for(int i = 0; i<len-1; i++)
        {
            if(ratings[i+1]>ratings[i])
                num[i+1]=num[i]+1;
        }
        for(int i = len-1; i>0; i--)
        {
            if(ratings[i-1]>ratings[i]&&num[i-1]<=num[i])
                num[i-1]=num[i]+1;
        }
        for(int i =0; i<len; i++)res += num[i];
    

  • 相关阅读:
    windows下Qt5.1.0配置android环境搭建 good
    Qt Focus事件,FocusInEvent()与FocusOutEvent()
    Python框架之Django
    WITH (NOLOCK)浅析
    区域、模板页与WebAPI初步
    对象映射工具AutoMapper介绍
    .NET大型B2C开源项目nopcommerce解析——项目结构
    企业管理系统集成
    oracle中sql语句的优化
    C#可扩展编程之MEF
  • 原文地址:https://www.cnblogs.com/AlvinZH/p/8045175.html
Copyright © 2011-2022 走看看