HDU 5697 刷题计划

来源:互联网 发布:python re 替换一部分 编辑:程序博客网 时间:2024/05/16 07:11
Problem Description
大赛将至,摆在你面前的是n道题目,第 i(1in) 道题目能提升 ai 点智力值,代码量为 bi KB,无聊值为 ci ,求至少提升m点智力值的情况下,所做题目代码量之和无聊值之和最小为多少。

样例解释:

选择第1、3、4道题
 

Input
多组测试数据

第一行两个整数n,m(0<n400)
接下来n行每行三个数,ai,bi,ci(0<bi,ci1000,0<ai800)
0<mai800
 

Output
一个数,至少提升m点智力值的情况下,所做题目代码量之和无聊值之和的最小值。
 

Sample Input
4 63 7 22 2 41 3 32 5 1
 

Sample Output

90

最小乘积生成树,差不多理解了这个算法的思想了,不过实现起来还是有点困难,数学太渣了。

暂时先这样了,之后再看看吧。

#pragma comment(linker, "/STACK:1024000000,1024000000")#include<map>#include<set>#include<queue>#include<stack>#include<cmath>#include<cstdio>#include<bitset>#include<string>#include<vector>#include<cstring>#include<iostream>#include<algorithm>#include<functional>using namespace std;typedef __int64 LL;const int low(int x) { return x&-x; }const int INF = 0x7FFFFFFF;const int mod = 1e9 + 7;const int maxn = 8e2 + 10;LL ans, dp[maxn];int x[maxn], y[maxn], z[maxn];int n, m, s;struct pii{int x, y;pii(int x = 0, int y = 0) :x(x), y(y) {}void read() { scanf("%d%d", &x, &y); }}f[maxn];pii operator +(pii a, pii b){return pii(a.x + b.x, a.y + b.y);}pii get(int X, int Y){dp[0] = 0;f[0] = pii(0, 0);for (int i = 1; i <= s; i++) dp[i] = 1LL << 62;for (int i = 1; i <= n; i++){LL v = (LL)y[i] * X + (LL)z[i] * Y;for (int j = s; j >= x[i]; j--){if (dp[j] <= dp[j - x[i]] + v) continue;dp[j] = dp[j - x[i]] + v;f[j] = f[j - x[i]] + pii(y[i], z[i]);}}int k = m;for (int i = m; i <= s; i++) if (dp[i] < dp[k]) k = i;ans = min(ans, (LL)f[k].x*f[k].y);return f[k];}void solve(pii x, pii y){pii t = get(x.y - y.y, y.x - x.x);if (1LL * (x.x - y.x)*(t.y - y.y) <= 1LL * (x.y - y.y)*(t.x - y.x)) return;solve(x, t), solve(t, y);}int main(){while (scanf("%d%d", &n, &m) != EOF){ans = 1LL << 62;s = 0;for (int i = 1; i <= n; i++){scanf("%d%d%d", &x[i], &y[i], &z[i]);s += x[i];}solve(get(1, 0), get(0, 1));printf("%I64d\n", ans);}return 0;}


0 0