洛谷P2062 分队问题

题目链接
一道容易想岔的题.
一开始用了贪心的方法先排序后从末尾开始扫描数组.idx的移动规则:移动到i-a[i]的位置直到将要越界为止.这个思路是有漏洞的,比如说下面这组数据:5 3 3 3 3 3 1 1
这么贪心输出的答案是2其实正确的答案是3.因为我们把最后一个3归入到第一组里得到的答案会更好.让剩下两个1各自一组.那么就得换个思路.
dp:从前面开始扫描数组.用i表示当前人数.dp[i]表示的是到第i个人时如果把他作为新的一队的话最多能划分为多少队,那么如果说a[i] > i的话,无法满足,dp[i] = 0,否则就把i-a[i]这个范围上的人划分为一组dp[i] = dp[i-a[i]]+1.不过这样的话dp[n]依然不一定是正确答案,因为我们可以把更大的范围划分为一组.就如同上面那个样例一样.我们不一定要划分最后5个人为一组,可以适当扩大范围,得出来的答案可能更优.我看有些博客是每次都往前扫描[1,i-a[i]]这个范围上的答案,让dp[n]最后为正确答案.虽然也可以得出正确答案,但显的有点麻烦了.其实只需要多添加一个ans变量,记录一下这个dp过程中得到的最大值是多少就可以了.
值得注意的是题目是保证有解的.如果说会出现无解的情况需再做考虑.
附上代码

#define LL long long
#include <iostream>
#include <cstdio>
#include <string.h>
#include <algorithm>
#include <cmath>
#include <vector>
using namespace std;
const int INF = 0x3f3f3f3f;
const int N = 1e6+10;
int a[N],dp[N];
int main(){
	ios::sync_with_stdio(false);
	int n;
	cin >> n;
	for(int i=1;i<=n;++i) cin >> a[i];
	sort(a+1,a+1+n);
	int ans=0;
	for(int i=1;i<=n;++i){
		if(a[i] > i) dp[i] = 0;
		else dp[i] = dp[i-a[i]] + 1;
		ans = max(dp[i],ans);
	}
	cout << ans;
	
	return 0;
}
/*

*/

猜你喜欢

转载自blog.csdn.net/weixin_45590210/article/details/104683039