ZCMU 2165 黄金矿工 (加限制条件的01背包)

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;
}

猜你喜欢

转载自blog.csdn.net/Gamer_Lee/article/details/81347276