乐***对
乐团派对
https://ac.nowcoder.com/acm/contest/6874/B
设f[i]表示前i个人最多能组成几支乐队
对于一个人a[i],若当前的人数小于a[i],即他在当前情况下怎样都不能组成乐队,则f[i]=0
否则,我们考虑与他组队的人则至少需要a[i]个,我们可以考虑将i-a[i]的人与他分配在一组, 此时的f[i]则有i-a[i]钱最大的f值转移过来(中间多的人随便塞到一队里就行)
对于无解的情况,只要有一个人的需要组队人数大于总人数,他就无论如何都不能组队,输出-1
#include<algorithm> #include<iostream> #include<iomanip> #include<cstring> #include<cstdio> #include<cmath> #define LL long long using namespace std; int read() { int s=0,bj=0; char ch=getchar(); while(ch<'0'||ch>'9')bj|=(ch=='-'),ch=getchar(); while(ch>='0'&&ch<='9')s=(s<<1)+(s<<3)+(ch^48),ch=getchar(); return bj?-s:s; } void printnum(int x) { if(x>9)printnum(x/10); putchar(x%10^48); } void print(int x,char ch) { if(x<0){putchar('-');x=-x;} printnum(x);putchar(ch); } int n,a[100005],f[100005],maxx[100005],bj; int main() { n=read(); for(int i=1;i<=n;++i){a[i]=read();bj=max(bj,a[i]);} if(bj>n){print(-1,'\n');return 0;}//判断无解情况 sort(a+1,a+n+1); for(int i=1;i<=n;++i) { if(i<a[i])f[i]=0;//此时无法组成乐队 else f[i]=maxx[i-a[i]]+1; maxx[i]=max(maxx[i-1],f[i]);//拿一个数组记录前面的最大值,方便转移 } print(f[n],'\n'); return 0; }
比赛时数据略水,被我一个贪心乱搞过去了^_^
//乱搞代码,勿抄 #include<algorithm> #include<iostream> #include<iomanip> #include<cstring> #include<cstdio> #include<cmath> #define LL long long using namespace std; const int INF=0x3f3f3f3f; int read() { int s=0,bj=0; char ch=getchar(); while(ch<'0'||ch>'9')bj|=(ch=='-'),ch=getchar(); while(ch>='0'&&ch<='9')s=(s<<1)+(s<<3)+(ch^48),ch=getchar(); return bj?-s:s; } void printnum(int x) { if(x>9)printnum(x/10); putchar(x%10^48); } void print(int x,char ch) { if(x<0){putchar('-');x=-x;} printnum(x);putchar(ch); } int n; int a[100005],ans,maxx; int main() { n=read(); for(int i=1;i<=n;++i){a[i]=read();maxx=max(maxx,a[i]);} if(maxx>n){puts("-1");return 0;} sort(a+1,a+n+1);int num=0; for(int i=1;i<=n;++i) { ++num; if(num>=a[i]){num=0;++ans;} } print(ans,'\n'); return 0; }