NOIP 模擬試題之 分組

2021-09-02 23:53:37 字數 1234 閱讀 3879

【問題描述】

mr_ he打算把自己棋下的 n 個選手分成若干組。每個選手都提出自己的要求,那就是第 i 個選手要求自己所屬的組的人數大等於a[i]人。在滿足所有選手的要求的前提下,mr_he打算最大化組的總數,請你來幫助他!。注意,分組時每個選手屬於且僅屬於一組。

【輸入格式】

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

【輸出格式】

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

【輸入樣例】52

1223

【輸出樣例】

【資料範圍】

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

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

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

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

可能是出於某種無腦的本能,一開始就想到要貪心去了,實際上最粗暴的貪心很好想就是把需求從大到小排序來直接選人。但是可以被卡掉,比如這組資料:1 1 1 3 4 4 4 4,發現一貪就是3組不巧可以分成4組。

有一種貪心是從小到大排序,然後一直選直到當前滿足這組裡面所有人的要求為止。出現最後有人分不完的時候就把上一次分組的人合併到這一組裡面來,直到分組人數符合要求位為止。

後來還是寫的dp,從小到大排序,設f(i)表示以i為結尾的元素中最大分組數量,g(i)表示前i個元素中最大的f值,f(i)=g(i-a[i])+1 ,g(i)=max(g(i-1),f(i))。這樣就處理了最開始貪心的不足,防止前面幾個人的要求少導致可以分出更多組來的情況出現。

ac**:

#include< iostream>

#include< cstdio>

#include< cstring>

#include< cstdlib>

#include< algorithm>

#include< cmath>

#include< queue>

#include< set>

#include< map>

#include< vector>

#include< cctype>

using namespace std;

const int maxn=1000005;

int n,a[maxn];

int f[maxn],g[maxn];

void _scanf(int &x)

bool cmp(int x,int y) { return x原文:

noip模擬賽 分組

分析 暴力分挺多,也挺好想的,個人感覺兩個特殊性質沒什麼卵用.對於k 1,n 1024的情況,從後往前貪心地分,如果能和上一組分在一起就分在一起,否則就再開一組,這樣可以保證字典序最小.ai 2就看前面有沒有2.有就不能分在一組.n 131072就不能再這樣二重迴圈列舉了,因為兩個數的和頂多只有26...

noip模擬賽 道路分組

分析 因為每一組編號都是連續的嘛,所以能分成一組的盡量分,每次加邊後dfs判斷一下1和n是否連通.有向圖的判連通沒有什麼很快的方法,特別注意,並查集是錯的!這個演算法可以得到60分.事實上每一次都不需要從點1開始dfs,因為之前很多點都遍歷到了,再從1開始會重複.如果新加的一條邊的起點沒有被訪問過,...

noip模擬賽 罪犯分組

分析 看了題後沒別的思路,感覺就是dp,普通dp的話狀態和方程實在是不好設計,觀察資料,發現n非常小,暗示了這道題要用狀壓dp來做.先列舉每個集合,再用o n 2 的暴力看這個集合內有多少個衝突,如果衝突數量不大於k,那麼就可以分成1個集合了,否則一定要分成多個集合,那麼列舉它的子集j,狀態轉移方程...