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=210;
struct node{
int x,y,w,v;
}p[maxn],now;
bool cmp(node a,node b)
{
if(a.x*b.y==a.y*b.x)return a.y<b.y;
else return a.x*b.y>a.y*b.x;
}
int w[maxn],v[maxn];
int dp[40010];
int n,t;
vector<node>edge[maxn];
int main()
{
cin>>n>>t;
for(int i=0;i<n;i++)
cin>>p[i].x>>p[i].y>>p[i].w>>p[i].v;
sort(p,p+n,cmp);
edge[0].push_back(p[0]);
int num=0;
for(int i=1;i<n;i++)
{
int len=edge[num].size();
if(edge[num][len-1].x*p[i].y==edge[num][len-1].y*p[i].x)
{
now.x=p[i].x; now.y=p[i].y;
now.w=p[i].w+edge[num][len-1].w;
now.v=p[i].v+edge[num][len-1].v;
edge[num].push_back(now);
}
else
{
num++;
now.x=p[i].x; now.y=p[i].y;
now.w=p[i].w; now.v=p[i].v;
edge[num].push_back(now);
}
}
memset(dp,0,sizeof(dp));
for(int i=0;i<=num;i++)
for(int j=t;j>=edge[i][0].w;j--)
for(int k=0;k<edge[i].size();k++)
dp[j]=max(dp[j],dp[j-edge[i][k].w]+edge[i][k].v);
printf("%d\n",dp[t]);
return 0;
}