Gold miner HDU - 4341(分组背包)

Gold miner

 题目链接:HDU - 4341

题意:大家都玩过黄金矿工吧,老头用钩子钩金矿,已知每个金矿的坐标,价值,以及老头把它钩上来花费的时间,问在T时间内老头能得到的金矿的最大价值,注意:在一条线上的金矿(就是在同一条以老头为起点的射线上),只有把靠近老头的先钩走,才能钩下一个;

思路:每块金矿只能钩一次,所以必定是01背包,但是在一条线上的金矿有依赖性,如果钩了第二块,那么必定钩了第一块;

这其实就是一组,把在同一直线上的金矿分为一组,钩到后边的金矿所需时间及得到的价值是前边金矿叠加起来,这样就是一个分组背包,每组中最多只能选一个;

#include <bits/stdc++.h>
using namespace std;
struct node{
	int x, y, t, v;
	bool operator < (const node &a)const{
		if(x*a.y==a.x*y) return y<a.y;
		return x*a.y<a.x*y;
	}
}g[210];
vector<node> vec[210];
int dp[40010];
int main(){
	int N, T, cas=0;
	while(~scanf("%d%d", &N, &T)){
		for(int i=0; i<N; i++){
			scanf("%d%d%d%d", &g[i].x, &g[i].y, &g[i].t, &g[i].v);
			vec[i].clear();
		}
		vec[N].clear();
		sort(g, g+N);
		int cnt=0;
		vec[++cnt].push_back(g[0]);
		for(int i=1; i<N; i++){
			if(g[i].x*g[i-1].y==g[i].y*g[i-1].x){
				g[i].t+=g[i-1].t;
				g[i].v+=g[i-1].v;
				vec[cnt].push_back(g[i]);
			}
			else{
				vec[++cnt].push_back(g[i]);
			}
		}
		memset(dp, 0, sizeof(dp));
		for(int k=1; k<=cnt; k++){
			for(int j=T; j>=0; j--){
				for(int i=0; i<vec[k].size()&&vec[k][i].t<=j; i++){
					dp[j]=max(dp[j], dp[j-vec[k][i].t]+vec[k][i].v);
				}
			}
		}
		printf("Case %d: %d\n", ++cas, dp[T]);
	}
	return 0;
} 

猜你喜欢

转载自blog.csdn.net/sirius_han/article/details/81195371
今日推荐