# Greedy# Priority Queue# Sorting

e593 - 12382 - Grid of Lamps

🔗 前往 ZeroJudge 原題

題目描述

題目描述一個 M x N 的網格,給定每行和每列至少需要亮燈的數量。初始時所有燈都是熄滅的。目標是計算點亮最少數量的燈,以滿足每行和每列的最低亮燈要求。

解題思路

這個問題可以使用貪心演算法來解決。首先,將每行的亮燈需求排序,然後將每列的亮燈需求放入優先佇列中。接著,從亮燈需求最高的行開始,盡可能使用優先佇列中的燈來滿足該行的需求。如果優先佇列中的燈不足以滿足該行的需求,則需要額外點亮燈。在處理完所有行後,優先佇列中剩餘的燈也需要被點亮。

具體步驟如下:

  1. 讀取 M 和 N。
  2. 讀取每行的亮燈需求,並將其排序。
  3. 讀取每列的亮燈需求,並將其放入優先佇列中。
  4. 從最後一行開始,迭代處理每一行。
    • 對於每一行,盡可能使用優先佇列中的燈來滿足該行的需求。
    • 如果優先佇列中的燈不足以滿足該行的需求,則額外點亮燈。
    • 將已使用的燈放入一個臨時佇列中。
    • 將臨時佇列中的燈放回優先佇列中。
  5. 處理完所有行後,將優先佇列中剩餘的燈全部點亮。
  6. 輸出總共點亮的燈的數量。

複雜度分析

  • 時間複雜度: O(N log N + M log M + M log N)
    • 排序每行的需求:O(M log M)
    • 建立優先佇列:O(N log N)
    • 迭代 M 行,每次從優先佇列中取出元素:O(M log N)
  • 空間複雜度: O(N + M)
    • 儲存每行的需求:O(M)
    • 優先佇列:O(N)
    • 臨時佇列:O(M)

程式碼

#include <iostream>
#include <algorithm>
#include <queue>
using namespace std;
int t,n,m,k,a[1005];
int main(){
	cin.tie(0); ios::sync_with_stdio(false);
	cin >> t;
	while(t--){
		int ans=0;
		cin >> n >> m;
		priority_queue <int> q;
		for(int i=0;i<n;++i){
			cin >> a[i];
		} 
		sort(a,a+n);
		for(int i=0;i<m;++i){
			cin >> k;
			if(k)q.push(k);
		}
		for(int i=n-1;i>=0;--i){
			queue <int> tmp;
			while(a[i]&&q.empty()==0){
				tmp.push(q.top()-1);
				q.pop();
				--a[i];
				++ans;
			}
			ans+=a[i];
			while(tmp.empty()==0){
				if(tmp.front())
					q.push(tmp.front());
				tmp.pop();
			}
		}
		while(q.empty()==0){
			ans+=q.top();
			q.pop();
		}
		cout << ans << "\n";
	} 
}

Discussion