#P3304. 第1题-优化器个数
          
                        
                                    
                      
        
              - 
          
          
                      1000ms
            
          
                      Tried: 470
            Accepted: 158
            Difficulty: 3
            
          
          
          
                       所属公司 : 
                              华为
                                
            
                        
              时间 :2025年7月9日-暑期实习
                              
                      
          
 
- 
                        算法标签>贪心算法          
 
第1题-优化器个数
题面描述
给定长度为N的数组 pvs,其中pvs[i]=1 表示位置i 有光伏板,pvs[i]=0 表示位置i为空。现在可以在空位上安装“光伏优化器”,只要一个光伏板的左边或者右边有优化器,该光伏板就能提升发电效率。请计算最少需要安装多少个优化器,才能使所有光伏板都能被提升;如果无法覆盖所有光伏板,则返回−1。
思路
- 
贪心策略:从左到右遍历。
 - 
遇到一个光伏板(即pvs[i]=1)且尚未被覆盖时,需要在它的邻位安装优化器。
 - 
优先尝试向右安装:
- 如果i+1<N 且pvs[i+1]=0,就在位置i+1 安装,并标记它能覆盖i以及未来可能的覆盖。
 - 否则再尝试向左:如果i−1≥0 且pvs[i−1]=0 且该位置还未安装过优化器,就在位置i−1安装。
 
 - 
若左右都无法安装,则无解,返回−1。
 - 
记录已安装优化器的集合
opt,以及被覆盖(即相邻有优化器)的光伏板标记数组covered,最终统计opt大小。 
此策略保证:
- “向右优先”能最大范围地往后覆盖,减少未来安装需求,达到最少安装数。
 - 单次遍历即可完成,时间复杂度O(N),空间复杂度O(N)。
 
C++
#include <bits/stdc++.h>
using namespace std;
int main() {
    ios::sync_with_stdio(false);
    cin.tie(nullptr);
    int N;
    cin >> N;
    vector<int> pvs(N);
    for (int i = 0; i < N; i++) {
        cin >> pvs[i];
    }
    vector<bool> covered(N, false);  // 标记光伏板是否已被覆盖
    vector<bool> hasOpt(N, false);   // 标记位置是否安装了优化器
    int ans = 0;
    for (int i = 0; i < N; i++) {
        if (pvs[i] == 1 && !covered[i]) {
            // 优先尝试向右安装优化器
            if (i + 1 < N && pvs[i+1] == 0 && !hasOpt[i+1]) {
                hasOpt[i+1] = true;
                ans++;
                // 安装后,覆盖左右的光伏板
                if (i >= 0 && pvs[i] == 1) covered[i] = true;
                if (i+2 < N && pvs[i+2] == 1) covered[i+2] = true;
            }
            // 右侧不行,尝试左侧
            else if (i - 1 >= 0 && pvs[i-1] == 0 && !hasOpt[i-1]) {
                hasOpt[i-1] = true;
                ans++;
                if (i-2 >= 0 && pvs[i-2] == 1) covered[i-2] = true;
                if (i < N && pvs[i] == 1) covered[i] = true;
            }
            else {
                // 无法安装覆盖此光伏板
                cout << -1;
                return 0;
            }
        }
    }
    cout << ans;
    return 0;
}
Python
def min_optimizers(pvs):
    n = len(pvs)
    covered = [False] * n    # 标记是否被覆盖
    has_opt = [False] * n    # 标记是否安装优化器
    ans = 0
    for i in range(n):
        if pvs[i] == 1 and not covered[i]:
            # 优先向右安装
            if i + 1 < n and pvs[i+1] == 0 and not has_opt[i+1]:
                has_opt[i+1] = True
                ans += 1
                covered[i] = True
                if i + 2 < n and pvs[i+2] == 1:
                    covered[i+2] = True
            # 向右不行,尝试左侧
            elif i - 1 >= 0 and pvs[i-1] == 0 and not has_opt[i-1]:
                has_opt[i-1] = True
                ans += 1
                covered[i] = True
                if i - 2 >= 0 and pvs[i-2] == 1:
                    covered[i-2] = True
            else:
                return -1
    return ans
# 读入输出部分
if __name__ == "__main__":
    N = int(input().strip())
    pvs = list(map(int, input().split()))
    print(min_optimizers(pvs))
Java
import java.util.*;
public class Main {
    public static int minOptimizers(int[] pvs) {
        int n = pvs.length;
        boolean[] covered = new boolean[n];  // 标记是否被覆盖
        boolean[] hasOpt = new boolean[n];   // 标记是否安装优化器
        int ans = 0;
        for (int i = 0; i < n; i++) {
            if (pvs[i] == 1 && !covered[i]) {
                // 优先尝试向右安装
                if (i + 1 < n && pvs[i+1] == 0 && !hasOpt[i+1]) {
                    hasOpt[i+1] = true;
                    ans++;
                    covered[i] = true;
                    if (i + 2 < n && pvs[i+2] == 1) {
                        covered[i+2] = true;
                    }
                }
                // 向右不行,尝试左侧
                else if (i - 1 >= 0 && pvs[i-1] == 0 && !hasOpt[i-1]) {
                    hasOpt[i-1] = true;
                    ans++;
                    covered[i] = true;
                    if (i - 2 >= 0 && pvs[i-2] == 1) {
                        covered[i-2] = true;
                    }
                }
                else {
                    return -1;
                }
            }
        }
        return ans;
    }
    public static void main(String[] args) {
        Scanner sc = new Scanner(System.in);
        int N = sc.nextInt();
        int[] pvs = new int[N];
        for (int i = 0; i < N; i++) {
            pvs[i] = sc.nextInt();
        }
        System.out.println(minOptimizers(pvs));
    }
}
        题目内容
光伏优化器可以用来提升光伏板的发电效率,现在需要给一排已经安装好的光伏板添加优化器。光伏板的安装位置用一个数组 pvs 表示,pvs[i]=1 表示该位置有光伏板,pvs[i]=0 表示该位为空。现在需要在空的位置上安装光伏优化器,以便提升所有光伏板的发电效率。(说明:如果光伏板的左边或者右边有优化器的话,就能提升发电的效率)。请计算使所有光伏板都提升发电效率所需要最少的光伏优化器数量,如果不能使所有光伏板都提升发电效率,则返回-1。
注:用例保证输入中一定有光伏板存在
输入描述
第一行一个整数 N ,表示已安装光伏板位置的长度,1<=N<=105
第二行是长度为 N 的数组 pvs 。pvs[i] 要么为 1 ,要么为 0 。
输出描述
最少的优化器的数量
样例1
输入
1
1
输出
-1
说明
没有空位可以安装优化器,无法使所有光伏板都升发电效率
样例2
输入
5
0 1 0 1 0
输出
1
说明
在下标 2 处安装 1 个优化器,可以提升下标 1 和下标 3 处光伏板的发电效率
样例3
输入
4
1 0 0 1
输出
2
说明
需要在下标 1 和下标 2 处分别安装 1 个优化器