zcmu2165(分组背包)

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

猜你喜欢

转载自blog.csdn.net/yu121380/article/details/81388091
今日推荐