题意:
每个克隆个体有n个属性 如果对于A、B两个个体 A的n个属性均不低于B的n个属性 那么B会被淘汰 问最多能有多少个体同时存活
思路:
根据数据大小猜一下是n^2的复杂度 往DP方面考虑一下
DP需要一个想法的支持 就是最优的那个集合中的元素的n个属性的和一定是一样的 为什么呢? 想象一下 假设最优的集合的属性和是5 这时你选过来一个和为6或者4的元素 那么至少会造成2个和为5的解从集合中被扔掉 选进1个扔掉2个明显是不合适的 而且这个最优的属性和必然为n个属性最大值的和的一半
假设每个属性的最大值为ti 那么sumt/2就是最优的属性和 那么问题就变成了 取n个数字 第i个数字在0到ti之间 问和为sumt/2的方案有几种 这就可以DP了
dp[i][j]表示第i个数字和为j的方案数 那么转移就是dp[i][j]=dp[i-1][j-ti]+dp[i-1][j-ti+1]+...+dp[i-1][j] 我们发现如果只用for需要3个循环 但是这是一个连续求和式子 用树状数组优化 就可以O(n^2logn)解决了
PS:这题杭电卡的时间比较死 不要每次循环都做到2000 因为sumt/2以后的数字全没用 所以别算
代码:
#include<cstdio>
#include<iostream>
#include<string>
#include<cstring>
#include<algorithm>
#include<cmath>
#include<map>
#include<set>
#include<vector>
#include<cassert>
using namespace std;
typedef long long LL;
#define Q 401
#define N 2002
#define M 200001
#define inf 2147483647
#define mod 1000000007
#define lowbit(x) (x&(-x))
int t, n, p;
int d[N];
LL f[N][N];
void add(int r, int x, int v) {
for (; x <= p; x += lowbit(x)) {
f[r][x] += v;
if (f[r][x] > mod)
f[r][x] -= mod;
}
}
LL sum(int r, int x) {
LL res = 0;
for (; x > 0; x -= lowbit(x))
res += f[r][x];
return res % mod;
}
int main() {
int i, j, k, tmp;
scanf("%d", &t);
while (t--) {
memset(f, 0, sizeof(f));
p = 0;
scanf("%d", &n);
for (i = 1; i <= n; i++) {
scanf("%d", &d[i]);
p += d[i];
}
p = p / 2 + 1;
for (i = 1; i <= d[1] + 1; i++)
add(1, i, 1);
for (i = 2; i <= n; i++) {
for (j = 1; j <= p; j++) {
k = j - d[i] - 1;
tmp = (sum(i - 1, j) - sum(i - 1, k) + mod) % mod;
add(i, j, tmp);
}
}
printf("%lld\n", (sum(n, p) - sum(n, p - 1) + mod) % mod);
}
return 0;
}
原文地址:http://blog.csdn.net/houserabbit/article/details/39367609