题解 P2062 【分队问题】

这道题可以用DP来做。

我们定义状态f[i]是当前的人数为i时的队伍数量的最大值。而i同时也代表现在是第几个人

根据题意。我们可以推出转移方程

  • i<a[i]时: f[i]=f[i1]

    • 当前队伍中的人数i不大于a[i]时,我们显然不能让i个选手自己组成一个队伍,只能让i个选手加入之前的队伍。
  • i>=a[i]时: f[i]=max(f[i1],f[ia[i]]+1)

    • 当前队伍中的人数ia[i]大时,就出现了两种情况。第一种仍是让i个选手加入之前的队伍,第二种则是让i个选手自成一个队伍,而这样的话自然得从f[ia[i]]中转移而来,因为i个选手自成一个队伍的条件是必须满足有至少a[i]个人。

    上面两个转移方程显然都是i之前转移而来的,所以循环顺序是顺序。

    而且因为循环中i是递增的,所以要先排序a数组。

    此时有些人可能觉得: 排序了之后ia[i]就不是对应的了。

    当然跟原来的数据来比不是对应的了,但是:这个做法跟i的顺序完全没有关系 ,只要保证排完之后还有这ia[i]就行了。这个性质也方便了上面的转移方程 (上面的做法直接默认排完之后的a[i]i是对应的了)

1|0AC代码

#include <cstdio> #include <algorithm> #define max(a,b) (a)>(b)?(a):(b) const int N = 1e6+10; int n; int a[N]; int f[N]; void Input() { scanf("%d",&n); for(int i=1; i<=n; i++) { scanf("%d",&a[i]); } } void Solve() { std::sort(a+1,a+n+1); for(int i=1; i<=n; i++) { if(i >= a[i]) { f[i]=max(f[i-1],f[i-a[i]]+1); } else { f[i]=f[i-1]; } } printf("%d",f[n]); } int main(void) { Input(); Solve(); return 0; }

写得非常详细了,望管理大大给过。


__EOF__

本文作者Kdlyh
本文链接https://www.cnblogs.com/kdlyh/p/17776981.html
关于博主:评论和私信会在第一时间回复。或者直接私信我。
版权声明:本博客所有文章除特别声明外,均采用 BY-NC-SA 许可协议。转载请注明出处!
声援博主:如果您觉得文章对您有帮助,可以点击文章右下角推荐一下。您的鼓励是博主的最大动力!
posted @   加固文明幻景  阅读(11)  评论(1编辑  收藏  举报  
相关博文:
阅读排行:
· 分享4款.NET开源、免费、实用的商城系统
· 全程不用写代码,我用AI程序员写了一个飞机大战
· MongoDB 8.0这个新功能碉堡了,比商业数据库还牛
· 白话解读 Dapr 1.15:你的「微服务管家」又秀新绝活了
· 记一次.NET内存居高不下排查解决与启示
点击右上角即可分享
微信分享提示