2165: 黄金矿工
Time Limit: 1 Sec Memory Limit: 128 MB
Submit: 72 Solved: 33
[Submit][Status][Web Board]
Description
Input
3 10
1 1 1 1
2 2 2 2
1 3 15 9
Output
3
HINT
30%的数据,0 < T ≤ 4000
100%的数据,N ≤ 200, 0 < T ≤ 40000
题目大意:
有n个黄金在地下,总时间为T,每个黄金的价值和挖上来需要的时间已知,每个黄金有自己的坐标位置,当两个黄金在同一直线上时需要先挖走前面的才能挖后面的,要求出在时间T内能挖到的最大价值。
想法:
这题是一个01背包问题的变型版,区别在于这题加了一个限制条件,即同一直线上的黄金要先拿走上面的才能拿下面的。我的解决方法是需要拿后面的黄金时把它和前面那个看成一个整体,采用结构存储数据,将黄金位置按斜率大小排序(相当于将在同一条直线上的黄金都放在一起),最后通过 mk[i] 来控制跳跃到上一个不相等的元素。
AC代码:
#include<bits/stdc++.h>
#define MAX 500
using namespace std;
struct Gold{
double k;
int t,v,s;
}gold[MAX];
bool compare(Gold a,Gold b)
{
if(a.k==b.k)
return a.s<b.s;
return a.k<b.k;
}
int main()
{
int n,T,i,j,x,y;
while(~scanf("%d%d",&n,&T))
{
for(i=1;i<=n;i++)
{
scanf("%d%d%d%d",&x,&y,&gold[i].t,&gold[i].v);
gold[i].k=1.0*y/x;
gold[i].s=x*x+y*y;
}
sort(gold+1,gold+n+1,compare);
int dp[40005],time=0;
memset(dp,0,sizeof(dp));
for(i=1;i<=n;i++)
{
gold[i].k==gold[i-1].k?time+=gold[i].t:time=gold[i].t;
for(j=T;j>=time;j--)
{
dp[j]=max(dp[j],dp[j-gold[i].t]+gold[i].v);
}
}
printf("%d\n",dp[T]);
}
return 0;
}