HDOJ  4341  Gold miner[条件背包]

来源:互联网 发布:苹果电脑设计软件下载 编辑:程序博客网 时间:2024/06/03 20:24

题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=4341

题目解析:给定时间让你求出能获得到的最大价值,对于每一次

显然,必须先拿走前面的金子才能拿后边的,所以排序处理共线情况。
然后进行背包即可,,,,,,

『将直线前面的视作一个背包,将前面和后面合在一起视作一个背包,然后就简化为01背包问题』

题解报告代码:

#include<stdio.h>
#include<iostream>
#include<cstring>
#include<algorithm>
#include<vector>
#define N 300
using namespace std;
struct Node
{
    intx,y,v,t;
} f[N];
bool operator<(Node a,Nodeb)        //sort()排序当在一条只线上的时候,按照距离长短排序
{
   if(a.y*b.x==a.x*b.y)
       return a.x*a.x+a.y*a.y<b.x*b.x+b.y*b.y;
    returna.y*b.x<a.x*b.y;
}
struct node
{
    intv,t;
}g[N];
vector<node> v[N];
int dp[50000];
int n,t;
int main()
{
    intcas=0;
   while(scanf("%d%d",&n,&t)==2)
    {
       memset(f,0,sizeof(f));
       for(int i=0;i<n;i++)
           scanf("%d %d %d%d",&f[i].x,&f[i].y,&f[i].t,&f[i].v);
       sort(f,f+n);
       for(inti=0;i<N;i++)     //每一次都要清空
           v[i].clear();
       int num=0;
       node tmp;
       tmp.v=f[0].v,tmp.t=f[0].t;
       v[0].push_back(tmp);
       for(int i=1;i<n;i++)
           if(f[i].x*f[i-1].y==f[i].y*f[i-1].x) 

           {//当在一条直线上的时候,因为排序的时候是把这条线的近的排在前面

                  //所以要取后面的必须去掉前面的,
               tmp.v+=f[i].v,tmp.t+=f[i].t;
               v[num].push_back(tmp);
           }
           else
           {
               tmp.v=f[i].v,tmp.t=f[i].t;
               v[++num].push_back(tmp);
           }
       memset(dp,0,sizeof(dp));

     //正常的背包问题,
       for(int k=0;k<=num;k++)
           for(int V=t;V>=0;V--)
               for(inti=0;i<v[k].size();i++)  //每次只能选择一种背包,择优选择
                   if(v[k][i].t<=V)
                       dp[V]=max(dp[V],dp[V-v[k][i].t]+v[k][i].v);
       printf("Case %d: %d\n",++cas,dp[t]);
    }
    return0;
}

0 0
原创粉丝点击