2165: 黄金矿工
Time Limit: 1 Sec Memory Limit: 128 MB
Submit: 86 Solved: 41
[Submit][Status][Web Board]
Description
Input
3 10
1 1 1 1
2 2 2 2
1 3 15 9
Output
3
Sample Input
Sample Output
HINT
-----sample2------
1 1 13 1
2 2 2 2
1 3 4 7
-----sample2-----
7
-----------
30%的数据,0 < T ≤ 4000
100%的数据,N ≤ 200, 0 < T ≤ 40000
解析:我们可以把在同一直线上的金矿假设为同一组,然后从第二个开始,也就是在一条直线上的次远离原点的金矿,它的价值和捕获时间就要加上在它之前的金矿,往下也是如此,这时候,就是可以变成分组背包问题。
#include<bits/stdc++.h>
using namespace std;
#define e exp(1)
#define pi acos(-1)
#define mod 1000000007
#define inf 0x3f3f3f3f
#define ll long long
#define ull unsigned long long
#define mem(a,b) memset(a,b,sizeof(a))
int gcd(int a,int b){return b?gcd(b,a%b):a;}
const int maxn=220;
int N,T;
int dp[50000];
struct node{
int x,y,t,v;
}p[maxn];
int cmp(node a,node b)//斜率从小到大排序,相同则靠近原点的先排
{
if(a.x*b.y==a.y*b.x)return a.y<b.y;
return a.x*b.y>b.x*a.y;
}
int main()
{
while(~scanf("%d%d",&N,&T))
{
for(int i=0; i<N; i++)
{
scanf("%d%d%d%d",&p[i].x,&p[i].y,&p[i].t,&p[i].v);
}
sort(p,p+N,cmp);
vector<node> ve[maxn];
ve[0].push_back(p[0]);
int cnt=0;
node now;
for(int i=1; i<N; i++)
{
int len=ve[cnt].size();
if(ve[cnt][len-1].x*p[i].y==ve[cnt][len-1].y*p[i].x)
{
now.x=p[i].x;now.y=p[i].y;
now.t=ve[cnt][len-1].t+p[i].t;now.v=ve[cnt][len-1].v+p[i].v;
ve[cnt].push_back(now);
}
else
{
cnt++;
now.x=p[i].x;now.y=p[i].y;
now.t=p[i].t;now.v=p[i].v;
ve[cnt].push_back(now);
}
}
mem(dp,0);
//分组背包模板
for(int i=0;i<=cnt;i++)
for(int j=T;j>=ve[i][0].t;j--)
for(int k=0;k<ve[i].size();k++)
dp[j]=max(dp[j],dp[j-ve[i][k].t]+ve[i][k].v);
printf("%d\n",dp[T]);
}
return 0;
}