您的位置:首页 > 编程语言 > Go语言

hdu4341 Gold miner 分组背包dp

2014-11-09 16:26 357 查看
题意:和黄金矿工差不多。。人在(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
;
vector<int>G
;
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;
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: