3 10 1 1 1 1 2 2 2 2 1 3 15 9 3 10 1 1 13 1 2 2 2 2 1 3 4 7
Case 1: 3 Case 2: 7
分组背包,主要是在一条线上时的分组,先按斜率排序,斜率相等的分一组,斜率相等的判断,x1/y1=x2/y2,可以转化为x1*y2=x2*y1,同理,斜率的大小也可以这样判
代码:
//515ms #include <iostream> #include <cstdio> #include <algorithm> #include <cstring> #include <cmath> #include <vector> using namespace std; const int maxn=40000+1000; int dp[maxn]; struct node { int x; int y; int t; int v; }edge[maxn]; vector<int> group[250]; bool cmp(node a,node b)//按斜率排序,斜率相等时按距离排序 { if(a.x*b.y==a.y*b.x) return a.x*a.x<b.x*b.x; return a.x*b.y<a.y*b.x; } int main() { int ca=1; int n,m; while(~scanf("%d%d",&n,&m)) { for(int i=0;i<n;i++) { scanf("%d%d%d%d",&edge[i].x,&edge[i].y,&edge[i].t,&edge[i].v); } sort(edge,edge+n,cmp); memset(dp,0,sizeof(dp)); for(int i=0;i<250;i++) group[i].clear(); int te=0; group[0].push_back(0); for(int i=1;i<n;i++)//将斜率相等的分到一组 { if(edge[i].x*edge[i-1].y==edge[i].y*edge[i-1].x) group[te].push_back(i); else { te=te+1; group[te].push_back(i); } } for(int i=0;i<=te;i++) { for(int j=m;j>=0;j--) { int t=0; int v=0; for(int k=0;k<group[i].size();k++) { int u=group[i][k]; t+=edge[u].t; v+=edge[u].v; if(j>=t) dp[j]=max(dp[j],dp[j-t]+v); } } } printf("Case %d: ",ca++); printf("%d\n",dp[m]); } return 0; }