1. 程式人生 > 其它 >重啟系統(等級考試4級 2021-03 T) 解題思路

重啟系統(等級考試4級 2021-03 T) 解題思路

【Horn Studio】程式設計專欄:重啟系統(等級考試4級 2021-03 T) 解題思路

題目

題目描述

小明幫助管理一個處理資料的計算系統,有N個待處理的任務,需要按照順序來完成這些任務, 即每次所完成任務的編號都要大於前一個完成任務的編號,且單個任務不可以分解完成。計算系統執行著一個奇怪的保護程式, 它限制了系統當前所能處理的資料量不能超過上次完成任務所處理的資料量。重啟系統可以使它立刻恢復到最高效能(一開始系統擁有最高效能, 最高效能大於任何待處理任務的資料量)。小明有一次重啟系統的許可權(也可以不使用),你能幫他算出最多能完成幾個任務嗎?

輸入

第一行: N (2 <= N <= 1000) 待處理的任務數 第二行: N個整數,每個任務的資料量

輸出

輸出只包括一行,這一行只包含一個整數,表示最多能完成的任務數。

樣例輸入複製

10
1 5 4 3 2 10 9 8 7 6

樣例輸出複製

9

提示

來源

思路

這道題跟上一登山,一 毛 一 樣!啊這就神奇了。不過還是與登山有稍微那麼億點不同,主要就是需要倒序一下,然後再進行一系列複雜的計算,時間複雜度有點大(n),不過最大也就1000,不慌。上一題的登山程式碼是這樣的:

#include <bits/stdc++.h>
using namespace std;
int n, down[1110], up[1110], a[1110];
 
int main()
{
    cin >> n;
    
for (int i = 1; i <= n; i++) cin >> a[i]; for (int i = 1; i <= n; i++) { up[i] = 1; for (int j = 1; j < i; j++) if (a[j] < a[i]) up[i] = max(up[i], up[j] + 1); } for (int i = n; i >= 1; i--) { down[i] = 1;
for (int j = n; j > i; j--) if (a[j] < a[i]) down[i] = max(down[i], down[j] + 1); } int res = 0; for(int i=1;i<=n;i++) res = max(res, up[i] + down[i] - 1); cout << res; return 0; }

我們將這個程式碼利用一下,大致思路是一樣的,不過,這個程式需要將陣列倒序之後在計算,我們可以用著一個程式碼解決:

reverse(taskmgr + 1, taskmgr + n + 1);

另外,在每一次序列結束後都要加上類似於斐波拉且數列(但它不是)的演算法,大體就是這種樣子:

for (int i = 2; i <= n; i++) {
        dpleft[i] = max(dpleft[i - 1], dpleft[i]);
    }

至此,我們摸清了他們之間的關係,接下來就很簡單了。

程式碼

#include <bits/stdc++.h>
using namespace std;
int dpleft[10005], dpright[10005], taskmgr[10005];
int n;
 
int main()
{
    cin >> n;
    for (int i = 1; i <= n; i++) {
        cin >> taskmgr[i];
        dpright[i] = dpleft[i] = 1;
    }
    reverse(taskmgr + 1, taskmgr + n + 1);
    for (int i = 1; i <= n; i++) {
        for (int j = 1; j < i; j++) {
            if (taskmgr[i] >= taskmgr[j]) {
                dpleft[i] = max(dpleft[i], dpleft[j] + 1);
            }
        }
    }
    for (int i = 2; i <= n; i++) {
        dpleft[i] = max(dpleft[i - 1], dpleft[i]);
    }
    for (int i = n - 1; i >= 1; i--) {
        for (int j = n; j > i; j--) {
            if (taskmgr[i] <= taskmgr[j]) {
                dpright[i] = max(dpright[i], dpright[j] + 1);
            }
        }
    }
    for (int i = n - 1; i >= 1; i--) {
        dpright[i] = max(dpright[i], dpright[i + 1]);
    }
    int ans = 0;
    for (int x = 1; x <= n; x++) {
        ans = max(ans, dpleft[x] + dpright[x + 1]);
    }
    cout << ans;
    return 0;
}