题意:
每个克隆个体有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