解题思路:
首先因为在同一直线上的黄金必须按顺序挖,所以可以将同一直线上的黄金所需时间和价值做前缀和处理,比如例1中,挖2 2的黄金之前必须先挖1 1,所以可以将2 2处黄金所需时间变为1+2,价值变为1+3,也就是说同一直线上的黄金都是同一组的,但是他们不可能同时存在,所以问题就转换为了分组背包问题。
代码:
#include<bits/stdc++.h>
using namespace std;
int dp[40005],N;
map<double,int>m;
struct kuang{
int x,y;
int t;
int v;
}a[205],b[205][205];
bool cmp(kuang a,kuang b)
{
double x=a.x/a.y;
double y=b.x/b.y;
if(x==y)return a.x<b.x;
else return x<y;
}
int main()
{
int T,i,ans=0;
scanf("%d%d",&N,&T);
memset(dp,0,sizeof(dp));
for(i=0;i<N;i++){
scanf("%d%d%d%d",&a[i].x,&a[i].y,&a[i].t,&a[i].v);
double x=(double)a[i].x/(double)a[i].y;
if(!m.count(x))m[x]=1;
else m[x]++;
}
sort(a,a+N,cmp);
int t,k,num[205],j=0;
for(i=0;i<N;i=i+t){
double x=(double)a[i].x/(double)a[i].y;
int z=0;
t=m[x];
//printf("t=%d\n",t);
b[j][z]=a[i];
for(k=i+1;k<i+t;k++){
z++;
b[j][z]=a[k];
b[j][z].v=b[j][z-1].v+a[k].v;
b[j][z].t=b[j][z-1].t+a[k].t;
}
z++;
num[j]=z;
j++;
}
for(i=0;i<m.size();i++){
for(j=T;j>=0;j--){
for(k=0;k<=num[i];k++){
if(j>=b[i][k].t)dp[j]=max(dp[j-b[i][k].t]+b[i][k].v,dp[j]);
ans=max(ans,dp[j]);
}
}
}
printf("%d\n",ans);
return 0;
}