小美要将N名员工分成若干组,且每组至少要有一名员工。每个组都会产生一个单位的收益,且对于第i名员工,如果其所在的组包含至少A[i]名员工(包括第i名员工自身),则该员工会额外贡献一个单位的收益。现在,小美请小团将N名员工分组,使得总收益最大。
小美要将N名员工分成若干组,且每组至少要有一名员工。每个组都会产生一个单位的收益,且对于第i名员工,如果其所在的组包含至少A[i]名员工(包括第i名员工自身),则该员工会额外贡献一个单位的收益。现在,小美请小团将N名员工分组,使得总收益最大。
第一行输入一个整数T(1<=T<=10),表示数据组数。
每组数据占两行,第一行输入一个整数N(1<=N<=10^5);
第二行输入N个由空格隔开的整数,表示A[1]到A[N](1<=A[i]<=N)。
每组数据输出占一行,输出一个整数,表示总收益的最大值。
4 3 2 3 3 4 2 2 2 2 5 3 2 5 1 4 6 2 3 4 1 3 2
4 6 6 8
对于第一组数据,将3名员工都分在一组;
对于第二组数据,将4名员工分成两组,每组2名;
对于第三组数据,将5名员工都分在一组;
对于第四组数据,将第4名员工分成一组,其他员工都分在另一组。
import java.io.BufferedReader; import java.io.InputStreamReader; import java.io.IOException; import java.util.Arrays; public class Main { public static void main(String[] args) throws IOException { BufferedReader br = new BufferedReader(new InputStreamReader(System.in)); int T = Integer.parseInt(br.readLine().trim()); while(T-- > 0){ int n = Integer.parseInt(br.readLine().trim()); String[] strA = br.readLine().trim().split(" "); int[] A = new int[n]; for(int i = 0; i < n; i++) A[i] = Integer.parseInt(strA[i]); // 对产生额外收益的“门槛”进行排序,先满足门槛低的员工 Arrays.sort(A); int[] dp = new int[n + 1]; // 初始化,每人一组至少有n的收益 dp[0] = n; int maxIncome = dp[0]; for(int i = 0; i < n; i++){ // 如果将i分配到前面的组能使得这个组人数至少为A[i],就会产生额外的1个单位收益 if(i + 1 >= A[i]) dp[i + 1] = dp[i + 1 - A[i]] + 1; maxIncome = Math.max(maxIncome, dp[i + 1]); } System.out.println(maxIncome); } } }
#include <bits/stdc++.h> using namespace std; int solve(vector<int>& A,int N); int main() { int T; cin>>T; for(int i=0;i<T;i++) { int N; cin>>N; vector<int> A(N); for(int j=0;j<N;j++) cin>>A[j]; cout<<solve(A,N)<<endl; } return 0; } int solve(vector<int>& A,int N) { //dp[i]表示从0~i-1(前i个)进行分组且i-1为所在组最后,其他单独分组,最大收益 vector<int> dp(N+1); dp[0]=N; //无分组考虑 //初始时分成n组,收益为n //进行排序,尽可能满足小的A[i]以获得最大收益 sort(A.begin(),A.end()); int maxIncome = N; //初始最大收益为M for(int i=1;i<=N;i++) { //dp转移:将i放在所在组内(如果能)组成A[i]长度,前面的从ap取得 if(i>=A[i-1]) //最后一个放分组能得到收益+1 { dp[i] = dp[i-A[i-1]]+1; //由排序易知这一组都满足 //如果不能放入,dp在此没有意义 maxIncome = max(maxIncome,dp[i]); } } return maxIncome; }
#include <bits/stdc++.h> using namespace std; int n, T, a[100005], dp[100005]; vector<pair<int, int> > e[100005]; int main() { scanf("%d", &T); while (T--) { for (int i = 0; i <= n + 1; i++) { e[i].clear(); } scanf("%d", &n); for (int i = 1; i <= n; i++) { scanf("%d", &a[i]); } sort(a + 1, a + n + 1, greater<int>()); for (int i = 1; i <= n; i++) { e[i].push_back(make_pair(i + 1, 1)); if (a[i] + i <= n + 1) { e[i].push_back(make_pair(a[i] + i, a[i] + 1)); } } dp[n + 1] = 0; for (int i = n; i >= 1; i--) { dp[i] = 0; for (int j = 0; j < e[i].size(); j++) { dp[i] = max(dp[i], dp[e[i][j].first] + e[i][j].second); } } printf("%d\n", dp[1]); } return 0; }
t=int(input()) while t: t-=1 n=int(input()) a=list(map(int, input().strip().split())) a.sort() res=n dp=[0 for _ in range(n+1)] dp[0]=n for i in range(n): if i+1>=a[i]: dp[i+1]=dp[i+1-a[i]]+1 res=max(res, dp[i+1]) print(res)