n块金子,T单位时间。
每块金子给出x,y坐标,得到需要的时间t,价值v。
在(0,0)位置取,共线的金子,必须按顺序,先取离原点近的。
可以整体排序,按斜率分组,在同一组里,按远近排序,计算前缀和。
比如1 2 3 ,变成 1 3 6,即取1块,取前2块,或取3块。
注意斜率用 x * a.y ?= y * a.x比较,而不是相除。
#include <iostream>
#include <cstdio>
#include <vector>
#include <map>
#include <iterator>
#include <cstring>
#include <algorithm>
using namespacestd;
const int maxn =200 + 5;
const int maxv =40000 + 5;
struct point{
int x,y,t,v;
booloperator < (constpoint &a) const {
returnx * a.y <y * a.x || (x * a.y ==y * a.x && (x *x + y *y) < (a.x * a.x + a.y * a.y));
}
}gold[maxn];
vector<int> mp[maxn];
int dp[maxv];
void init(int n)
{
memset(dp,0,sizeof(dp));
for (int i =0; i < n; i ++) {
mp[i].clear();
}
for (int i =0; i < n; i ++) {
point &p =gold[i];
p.x = p.y = p.t = p.v = 0;
}
}
int main()
{
int n,T;
int kase =0;
while(scanf("%d%d",&n,&T) !=EOF)
{
init(n);
for (int i =0; i < n; i ++) {
scanf("%d%d%d%d",&gold[i].x,&gold[i].y,&gold[i].t,&gold[i].v);
}
sort(gold,gold + n);
int gp =0;
mp[gp].push_back(0);
for (int i =1; i < n; i ++) {
if (gold[i].x *gold[i - 1].y !=gold[i].y *gold[i - 1].x) {
gp ++;
}
else {
gold[i].t +=gold[i - 1].t;
gold[i].v +=gold[i - 1].v;
}
mp[gp].push_back(i);
}
for (int i =0; i <= gp; i ++) {
for (int j = T; j >=0; j --) {
for (int k =0; k < mp[i].size(); k ++) {
if(j -gold[mp[i][k]].t >=0)
dp[j] =max(dp[j],dp[j -gold[mp[i][k]].t] +gold[mp[i][k]].v);
}
}
}
printf("Case %d: %d\n",++kase,*max_element(dp,dp + T + 1));
}
return0;
}