DP 分隊問題

2021-07-24 11:44:38 字數 1254 閱讀 4751

題目描述

給定n 個選手,將他們分成若干只隊伍。其中第i 個選手要求自己所屬的隊伍的人數大等於a[i]人。

在滿足所有選手的要求的前提下,最大化隊伍的總數。

注:每個選手屬於且僅屬於一支隊伍。

輸入格式

第一行乙個整數n,表示人數。

以下n 行,每行乙個整數表示a[i]。

輸出格式

輸出隊伍總數的最大值。資料保證有解。

樣例輸入52

1223

樣例輸出2

資料範圍

對於20%的資料,n <= 10

對於40%的資料,n <= 1000

對於60%的資料,n <= 10000

對於100%的資料,1 <= n <= 10^6

solution:

最開始想到貪心。

先把a[ i ] 排序。

然後我們從大到小依次加入隊伍就好了。

3 2 2 2 1

先把 3 2 2 加入

再把 2 1 加入 就可以了。

但是實際上這東西是錯的。 例子

3 3 3 3 2 2 1

變成             3 3 3。3 2 1。

實際上可以  1 。2 2。3 3 3 3

所以貪心有問題。

考慮dp

f[i] 表示前 i 個人可以最多分成的隊伍數目。

顯然 如果第 i 個人對隊伍數目做出貢獻,當且僅當 滿足了 第i個人的要求 a[i] 

所以 f [ i ] =max +1  其中 0 < k < = i - a[ i ]

所以 可以維護 乙個 最大值 g [ k ] 表示 f[ 1..k ] 的 最大值。

每次修改 了 f [ i ] 的話 就是 g [ i ] =max

這就避免了每次查詢 max f [ k ] 都要從 頭 到 i- a [ i ] 掃瞄一遍。 

所以時間複雜度 為 o(n)

#include#include#include#includeusing namespace std;

const int maxn=1e6+5,inf=x3f3f3f3f;

inline void _read(int &x)

for(x=0;t>='0'&&t<='9';t=getchar())x=x*10+t-'0';

if(!sign)x=-x;

}int n,f[maxn],s[maxn],g[maxn];

int main()

cout<

NKOJ 3860 分隊問題(DP 字首和優化)

問題描述 給定 n 個選手,將他們分成若干只隊伍。其中第 i 個選手要求自己所屬的隊 伍的人數大等於 a i 人。在滿足所有選手的要求的前提下,最大化隊伍的總數。注 每個選手屬於且僅屬於一支隊伍。輸入格式 第一行乙個整數 n,表示人數。以下 n 行,每行乙個整數表示 a i 輸出格式 輸出隊伍總數的...

洛谷P2062 分隊問題

題目鏈結 一道容易想岔的題.一開始用了貪心的方法先排序後從末尾開始掃瞄陣列.idx的移動規則 移動到i a i 的位置直到將要越界為止.這個思路是有漏洞的,比如說下面這組資料 5 3 3 3 3 3 1 1 這麼貪心輸出的答案是2其實正確的答案是3.因為我們把最後乙個3歸入到第一組裡得到的答案會更好...

記爬蟲小分隊(六)

import requests from bs4 import beautifulsoup start url response requests.get start url,headers headers text soup beautifulsoup response,html.parser i...