2 solutions

  • 0
    @ 2024-10-26 16:02:18
    import sys
    sys.setrecursionlimit(1000000)
    n = int(input())
    a = [0]+list(map(int,input().split()))
    def sov(l,r):
        if l>r:
            return 0
        elif l == r:
            return 2
        min_h = min(a[l:r+1])
        res = 1
        i = l
        while i<=r:
            if a[i]>min_h:
                start = i
                while i<=r and a[i]>min_h:
                    i+=1
                res+=sov(start,i-1)
            else:
                i+=1
        return res
    print(sov(1,n))
    
    • 0
      @ 2024-9-20 11:50:06

      题面解释:

      为了最小化检查数据中心服务器的时间,我们可以采取以下策略:首先,使用行检查,能够同时检查多行服务器,耗时1秒;然后,使用列检查,单列检查耗时2秒。我们需要读取机架数量及每个机架的服务器数量,并找出最大的服务器数量来决定检查方式。优先进行行检查,尽可能多地覆盖服务器,再用列检查完成剩余的检查。代码实现通过标记已检查的行和计算总耗时来得到最终结果。通过这种方式,我们可以高效地确保所有服务器都得到检查,达到最小的时间消耗。

      思路:贪心+递归

      对一个数组arr,对min(arr)进行一个行操作。剩下的区间递归进行。直到l = r , 进行列操作 具体细节看代码注释

      题解

      本题旨在计算对一组服务器高度数组进行检查所需的最小代价。代价的计算方式分为两部分:行操作和列操作。具体来说,我们将根据数组中的最小值执行行操作,并在处理完所有行之后,对单个服务器进行列操作。

      1. 行操作: 如果区间内有多个服务器的高度大于当前最小值,我们将这些服务器的高度减少到最小值,这一过程的代价为1秒。此时,我们会递归地处理剩余的区间。

      2. 列操作: 当区间缩小至仅包含一个服务器时,必须进行列操作,此时的代价为2秒。

      通过这样的递归操作,我们可以有效地计算出整个数组的最小检查代价。算法的核心在于寻找当前区间的最小值,并在此基础上递归处理,直至每个服务器都被检查完毕。

      代码分析

      • 输入部分: 首先读取服务器数量和高度。
      • 递归函数 minCost:
        • 基本条件: 处理了左边界大于右边界和只包含一个元素的特殊情况。
        • 最小值计算: 遍历当前区间以找到最小的服务器高度。
        • 行操作: 使用循环遍历区间,处理所有大于最小值的服务器,进行递归调用。
      • 输出部分: 打印计算得到的最小代价。

      代码

      java

      import java.util.Scanner;
      
      public class Main {
      
          static int[] h;
      
          public static void main(String[] args) {
              Scanner sc = new Scanner(System.in);
              int n = sc.nextInt();
              h = new int[n + 1];  // 1-based indexing
              for (int i = 1; i <= n; i++) {
                  h[i] = sc.nextInt();
              }
              // 计算并输出最小操作代价
              System.out.println(minCost(1, n));
          }
      
          // 计算区间 [l, r] 的最小代价
          static int minCost(int l, int r) {
              if (l > r) {
                  return 0;
              }
              if (l == r) {
                  return 2; // 单个服务器默认为单列操作
              }
      
              int minH = Integer.MAX_VALUE;
              for (int i = l; i <= r; i++) {
                  minH = Math.min(minH, h[i]);
              }
      
              // 行操作
              int cost1 = 1;
              int i = l;
              while (i <= r) {
                  if (h[i] > minH) {
                      int start = i;
                      while (i <= r && h[i] > minH) {
                          i++;
                      }
                      cost1 += minCost(start, i - 1);
                  } else {
                      i++;
                  }
              }
              return cost1;
          }
      }
      
      

      python

      import sys
      # 递归深度设置为1000000
      sys.setrecursionlimit(1000000)
      
      n_and_rest = sys.stdin.read().split()
      n = int(n_and_rest[0])
      h = list(map(int, n_and_rest[1:n+1]))
      h = [0] + h  # 1-based indexing
      
      def min_cost(l, r):
          if l > r:
              # 空区间的操作代价为0
              return 0
          if l == r:
              # 一个服务器的操作默认为单列操作
              return 2 
          min_h = min(h[l:r+1])
          # 操作1: 用行操作,找到<不是最小高度>的连续区间
          cost1 = 1
          i = l
          while i <= r:
              # 找到连续区间
              if h[i] > min_h:
                  # 找到连续区间的起始位置
                  start = i
                  # 找到连续区间的终止位置
                  while i <= r and h[i] > min_h:
                      i += 1
                  # 递归计算连续区间的最小代价
                  cost1 += min_cost(start, i - 1)
              else:
                  i += 1
          return cost1
      
      total_min_cost = min_cost(1, n)
      print(total_min_cost)
      
      

      cpp

      #include <iostream>
      #include <vector>
      #include <algorithm>
      #include <climits>
      using namespace std;
      
      vector<int> h;  // 服务器高度数组
      
      // 计算区间 [l, r] 的最小代价
      int minCost(int l, int r) {
          // 如果左边界大于右边界,返回0(无操作)
          if (l > r) {
              return 0;
          }
          
          // 如果区间只包含一个服务器,返回列操作的代价2
          if (l == r) {
              return 2;  
          }
      
          // 找到当前区间的最小高度
          int minH = INT_MAX;  
          for (int i = l; i <= r; i++) {
              minH = min(minH, h[i]);  // 更新当前最小高度
          }
      
          // 进行行操作,初始代价为1秒
          int cost1 = 1;  
          int i = l;  // 从左边界开始遍历
          while (i <= r) {
              // 如果当前服务器的高度大于最小值
              if (h[i] > minH) {
                  int start = i;  // 记录当前区间的起始位置
                  // 向右移动,直到找到不再大于最小值的服务器
                  while (i <= r && h[i] > minH) {
                      i++;
                  }
                  // 对于当前找到的区间,递归计算其代价
                  cost1 += minCost(start, i - 1);
              } else {
                  // 如果当前服务器高度不大于最小值,继续向右移动
                  i++;
              }
          }
      
          return cost1;  // 返回当前区间的总代价
      }
      
      int main() {
          int n;
          cin >> n;  // 输入服务器数量
          h.resize(n + 1);  // 调整数组大小以便使用1-based索引
          for (int i = 1; i <= n; i++) {
              cin >> h[i];  // 输入每个服务器的高度
          }
      
          cout << minCost(1, n) << endl;  // 输出从1到n的最小检查代价
          return 0;
      }
      
      

      OJ会员可以通过点击题目上方《已通过》查看其他通过代码来学习。

      • 1

      2024.9.19-秋招(留学生)-第2题-服务器健康巡检

      Information

      ID
      123
      Time
      1000ms
      Memory
      256MiB
      Difficulty
      5
      Tags
      # Submissions
      240
      Accepted
      82
      Uploaded By