本文主要是介绍hdu4341 Gold miner 分组背包dp,希望对大家解决编程问题提供一定的参考价值,需要的开发者们随着小编来一起学习吧!
题意:和黄金矿工差不多。。人在(0,0)。有n种金,游戏时间为T。告诉你每种金的位置(x,y),获得该金需要的时间的t,以及它的
价值。且若人和多块金子共线时,只能先取最近的金子。问在游戏时间内可获得最大价值。
思路:对于共线的金,我们将其分为一组,并按照距(0,0)的距离排序,那么选该点的价值为前面所有的价值,花费的时间也是前
面所有花费的时间。对于每组我们相当于只选一个,之后背包跑一下,详见代码:
// file name: hdu4341.cpp //
// author: kereo //
// create time: 2014年11月08日 星期六 17时42分41秒 //
//***********************************//
#include<iostream>
#include<cstdio>
#include<cstring>
#include<queue>
#include<set>
#include<map>
#include<vector>
#include<stack>
#include<cmath>
#include<string>
#include<algorithm>
using namespace std;
typedef long long ll;
const int sigma_size=26;
const int N=200+100;
const int MAXN=40000+100;
const double eps=1e-8;
const int inf=0x3fffffff;
const int mod=1000000000+7;
#define L(x) (x<<1)
#define R(x) (x<<1|1)
int n,T;
int dp[MAXN],res[MAXN],st[MAXN];
struct node{int x,y,t,val;
}p[N];
vector<int>G[N];
bool judge(node a,node b){return a.x*b.y == b.x*a.y;
}
bool cmp(int a,int b){return p[a].x*p[a].x+p[a].y*p[a].y<p[b].x*p[b].x+p[b].y*p[b].y;
}
int main()
{int kase=0;while(~scanf("%d%d",&n,&T)){for(int i=1;i<=n;i++)scanf("%d%d%d%d",&p[i].x,&p[i].y,&p[i].t,&p[i].val);int cnt=0;for(int i=1;i<=n;i++){int flag=1;for(int j=0;j<cnt;j++){if(!flag)break;if(judge(p[i],p[G[j][0]])){G[j].push_back(i);flag=0;}}if(!flag)continue;G[cnt].clear(); G[cnt++].push_back(i);}memset(dp,0,sizeof(dp));for(int i=0;i<cnt;i++){sort(G[i].begin(),G[i].end(),cmp);memcpy(res,dp,sizeof(dp));memcpy(st,dp,sizeof(dp));int val=0,t=0;for(int j=0;j<G[i].size();j++){int id=G[i][j];t+=p[id].t; val+=p[id].val;if(t>T)break;for(int k=T;k>=t;k--)if(res[k]<=res[k-t]+val)res[k]=res[k-t]+val;for(int k=t;k<=T;k++)dp[k]=max(dp[k],res[k]);memcpy(res,st,sizeof(st));}}printf("Case %d: %d\n",++kase,dp[T]);}return 0;
}
这篇关于hdu4341 Gold miner 分组背包dp的文章就介绍到这儿,希望我们推荐的文章对编程师们有所帮助!