What comes after, tiny fra|

落花月朦胧

园龄:3年6个月粉丝:14关注:10

P2062 分队问题 题解

P2062 分队问题 题解

题目大意

N 名选手, 现在要把他们分到若干队,每个选手要求他的队伍的人数必须要大于等于 ai, 求最多可以分多少个队伍。

确定算法

贪心思想

这道题没有标签,差评,初次看题没有任何思路,看到最大化队伍数量就想到了贪心,。

在打代码的过程中发现贪心会发生错误, 每次贪心后并没有考虑到后面的人对队伍的限制,没有满足最优决策兴致勃勃的证明了半天贪心错误, 题解里有人证出来了????

DP思想

话说贪心和DP总是在一起的,既然贪心错误那就DP!

首先考虑定义的状态,用 f[i] 表示前 i 个人中最大的队伍数量。

那么阶段就是 1N
答案就是 f[n]

使用DP解决这道题目

首先我们要进行排序, 保证决策的正确(这不就是贪心吗?

可以先特判一下, 如果要求的最大的人数都大于了总人数,直接输出 0

2 种情况讨论, 第一种情况是当前人数不大于 i,另外一种是人数大于等于 i

当前的 a[i] 不大于 i , 就只有一个决策

f[i]=f[i1]

反之当前的 aii 了,即有 2 个决策, 要么加, 要么不加。

转移方程就是

f[i]=max(f[i1],f[ia[i]+1)

应该很好推吧

代码

#include<bits/stdc++.h>
using namespace std;
inline int read() {
int x = 0, f = 1; char ch = getchar();
while (ch < '0' || ch > '9') f |= ch == '-' ? 1 : -1, ch = getchar();
while (ch >= '0' && ch <= '9') x = (x << 1) + (x << 3) + (ch ^ 48), ch = getchar();
return x;
}
inline void print(int x){
char P[105];int w=0;if(x==0){putchar('0');return;}
if(x<0) putchar('-'),x=-x;
while(x) P[++w]=x%10+'0',x/=10;
for(int i=w; i>=1; i--) putchar(P[i]);
}
const int N = 1e6;
int n, a[N + 1], ans, f[N + 1];
int main() {
n = read();
for (int i = 1; i <= n; i++) a[i] = max(1, read());
sort(a + 1, a + n + 1);
if (a[n] > n) {
puts("0");
return 0;
}
for (int i = 1; i <= n; i++) {
if (a[i] > i) f[i] = f[i - 1];
else f[i] = max(f[i - 1], f[i - a[i]] + 1);
}
print(f[n]);
return 0;
}

本文作者:Falling-flowers 的 blog

本文链接:https://www.cnblogs.com/falling-flowers/p/15871911.html

版权声明:本作品采用知识共享署名-非商业性使用-禁止演绎 2.5 中国大陆许可协议进行许可。

posted @   落花月朦胧  阅读(70)  评论(1编辑  收藏  举报
点击右上角即可分享
微信分享提示
评论
收藏
关注
推荐
深色
回顶
收起