zoukankan      html  css  js  c++  java
  • Codeforces Round #523 (Div. 2) B Views Matter

    传送门

    https://www.cnblogs.com/violet-acmer/p/10005351.html

    这是一道贪心题么????

    题意:

      某展览馆展览一个物品,此物品有n堆,第 i 堆有a[ i ]个正方块,问最多可以去除多少个正方块,使得其俯视图与右视图的保持不变。

      并且去除某正方块a下方的正方块时,是不会导致a方块下降的(无重力)。

    题解:

      相关变量解释:

    1 int n,m;
    2 ll sum;//所有的方块
    3 int a[maxn];//a[i] : 第i堆有a[i]个正方块
    4 int index;//来到第index堆物品
    5 int maxHigh;//当前保留下来的正方块的最大高度
    6 int remain;//必须保留下的正方块个数

      单纯的解释,貌似,不太会,那就用个样例解释吧,哈哈哈。

      例如: 

    1 Input
    2 10 17
    3 12 16 6 9 12 6 12 1 12 13
    4 
    5 Output
    6 83

      首先,将a[ ]数组按照从小到大的规则排序,排好序后,配图如下:

                       

      大体思路是:

        (1):从第一堆物品开始遍历,定义变量h=a[ i ]-maxHigh,根据maxHigh的定义可知,在第一堆物品之前,是没有方块的,所以,初始化maxHigh=0,那么h代表的就是

        当前堆需要保留的最多的方块数,定义变量len=n-index+1,index表示的是当前来到第index堆,那么len就表示在这之后还有多少堆。

        (2):判断是否可以组成h*h的大正方形,也就是判断len是否大于等于h:

          ①如果可以,例如图片中的红方框,如果可以,那么h*h的正方形上的对角线上的方块是一定要保留的,且是当前正方形需要保留的最少的方块数。

          ②反之,len*len的正方形最少需要保留的方块个数也是其对角线的方块个数。

        (3):当index > n 时,判断maxHigh是否达到了最大高度a[n],如果没有,还需额外保留a[n]-maxHigh个正方块。

    具体细节看代码:

     1 #include<iostream>
     2 #include<cstdio>
     3 #include<algorithm>
     4 using namespace std;
     5 #define ll long long
     6 const int maxn=1e5+10;
     7 
     8 int n,m;
     9 ll sum;
    10 int a[maxn];
    11 
    12 ll Solve()
    13 {
    14     sort(a+1,a+n+1);
    15     if(n == 1)
    16         return 0;
    17     ll remain=0;
    18     int index=1,maxHigh=0;
    19     while(index <= n)
    20     {
    21         int h=a[index]-maxHigh;
    22         int len=n-index+1;
    23         if(len >= h)//可以形成h*h的正方形
    24         {
    25             //注意需要特判h == 0的情况
    26             remain += (h == 0 ? 1:h);//需要保留的最少的方块数为h个
    27             index += (h == 0 ? 1:h);//[index,index+h]已经保留过正方块了,直接来到index+h堆
    28             maxHigh += h;//更新前index堆达到的最大高度
    29         }
    30         else//可以形成len*len的正方形
    31         {
    32             remain += len;
    33             index += len;
    34             maxHigh += len;
    35         }
    36     }
    37     remain += (a[n]-maxHigh);//步骤(3)
    38     return sum-remain;
    39 }
    40 
    41 int main()
    42 {
    43     cin>>n>>m;
    44     for(int i=1;i <= n;++i)
    45         cin>>a[i],sum += a[i];
    46     cout<<Solve();
    47 }
    View Code
  • 相关阅读:
    线程同步
    子程序循环10次,接着主程序循环100次,然后子程序又循环10次,主程序循环100次,这样循环50次
    MissingNumber缺失的数字,FirstMissingPositive第一个缺失的正数
    数字组合问题:Combination,CombinationSum,CombinationSum2,CombinationSum3
    Count and Say,统计并输出,利用递归,和斐波那契数列原理一样。
    Sudoku Solver, 求数独
    Valid sudoku, 是否是有效的数独
    Search insert position, 查找插入位置
    用excel来做项目管理?
    Redis 在 SNS 类应用中的最佳实践有哪些?
  • 原文地址:https://www.cnblogs.com/violet-acmer/p/10028786.html
Copyright © 2011-2022 走看看