然后在同一个组内需要处理下。比如(2,3)是先要抓2才能抓3的。那就把2,3的t和v加起来给3。这样2,3就只能取一个了,就变成分组的背包问题了。
#include<stdio.h>
#include<string.h>
#include<algorithm>
#include<iostream>
using namespace std;
const int MAXN=220;
struct Node
{
int x,y;
int v,t;
}node[MAXN];
bool cmp(Node a,Node b)//按照斜率从小到到排序,斜率相同按照距原点距离排序
{
int x1=a.x;
int y1=a.y;
int x2=b.x;
int y2=b.y;
if(y1*x2==y2*x1)return y1<y2;
return y1*x2<y2*x1;
}
int group[MAXN][MAXN];//group[i][0]表示第i组的总的点数,group[i][1-group[i][0]]就是该组点的编号
int cnt;//组数
int f[50000];
int solve(int T)
{
memset(f,0,sizeof(f));//可以不装满的背包,初始化为0
for(int i=0;i<cnt;i++)//对所有的组
for(int t=T;t>=0;t--)
for(int k=1;k<=group[i][0];k++)
{
if(t-node[group[i][k]].t>=0)
f[t]=max(f[t],f[t-node[group[i][k]].t]+node[group[i][k]].v);
//printf("%d %d\n",t,f[t]);
}
return f[T];
}
int main()
{
// freopen("in.txt","r",stdin);
// freopen("out.txt","w",stdout);
int N,T;
int iCase=0;
while(scanf("%d%d",&N,&T)!=EOF)
{
iCase++;
for(int i=0;i<N;i++)
scanf("%d%d%d%d",&node[i].x,&node[i].y,&node[i].t,&node[i].v);
sort(node,node+N,cmp);
cnt=-1;
for(int i=0;i<N;i++)
{
cnt++;
group[cnt][0]=0;
group[cnt][++group[cnt][0]]=i;
int x1=node[i].x;
int y1=node[i].y;
int a=node[i].t;
int b=node[i].v;
for(i++;i<N;i++)
{
int x2=node[i].x;
int y2=node[i].y;
a+=node[i].t;
b+=node[i].v;
if(y1*x2==y2*x1)
{
group[cnt][++group[cnt][0]]=i;
node[i].t=a;
node[i].v=b;
}
else {i--;break;}
}
}
cnt++;
//for(int i=0;i<N;i++)printf("%d %d\n",node[i].x,node[i].y);
//for(int i=0;i<cnt;i++)printf("%d\n",group[i][0]);
printf("Case %d: ",iCase);
printf("%d\n",solve(T));
}
return 0;
}