Gold miner
题意:大家都玩过黄金矿工吧,老头用钩子钩金矿,已知每个金矿的坐标,价值,以及老头把它钩上来花费的时间,问在T时间内老头能得到的金矿的最大价值,注意:在一条线上的金矿(就是在同一条以老头为起点的射线上),只有把靠近老头的先钩走,才能钩下一个;
思路:每块金矿只能钩一次,所以必定是01背包,但是在一条线上的金矿有依赖性,如果钩了第二块,那么必定钩了第一块;
这其实就是一组,把在同一直线上的金矿分为一组,钩到后边的金矿所需时间及得到的价值是前边金矿叠加起来,这样就是一个分组背包,每组中最多只能选一个;
#include <bits/stdc++.h>
using namespace std;
struct node{
int x, y, t, v;
bool operator < (const node &a)const{
if(x*a.y==a.x*y) return y<a.y;
return x*a.y<a.x*y;
}
}g[210];
vector<node> vec[210];
int dp[40010];
int main(){
int N, T, cas=0;
while(~scanf("%d%d", &N, &T)){
for(int i=0; i<N; i++){
scanf("%d%d%d%d", &g[i].x, &g[i].y, &g[i].t, &g[i].v);
vec[i].clear();
}
vec[N].clear();
sort(g, g+N);
int cnt=0;
vec[++cnt].push_back(g[0]);
for(int i=1; i<N; i++){
if(g[i].x*g[i-1].y==g[i].y*g[i-1].x){
g[i].t+=g[i-1].t;
g[i].v+=g[i-1].v;
vec[cnt].push_back(g[i]);
}
else{
vec[++cnt].push_back(g[i]);
}
}
memset(dp, 0, sizeof(dp));
for(int k=1; k<=cnt; k++){
for(int j=T; j>=0; j--){
for(int i=0; i<vec[k].size()&&vec[k][i].t<=j; i++){
dp[j]=max(dp[j], dp[j-vec[k][i].t]+vec[k][i].v);
}
}
}
printf("Case %d: %d\n", ++cas, dp[T]);
}
return 0;
}