01背包(分组) HDOJ 4341 Gold miner

题目传送门

题意:有n个金矿,每个金矿有抓取的消耗的时间和价值,矿工在原点,问在T时间内能得到的最大的价值

分析:唯一和01背包不同的是金矿可能共线,也就是抓取近的金矿后才能抓后面共线的金矿。这是分组背包问题,方法是将点按照斜率排序,如果相等按照距离原点远近排序,将斜率相等的点分成一组,每组的点累加上前面的点的时间和价值,这样每组只选一个点,就是01背包了

收获:分组背包问题

代码:

/************************************************
* Author        :Running_Time
* Created Time  :2015-8-27 8:48:05
* File Name     :J.cpp
 ************************************************/

#include <cstdio>
#include <algorithm>
#include <iostream>
#include <sstream>
#include <cstring>
#include <cmath>
#include <string>
#include <vector>
#include <queue>
#include <deque>
#include <stack>
#include <list>
#include <map>
#include <set>
#include <bitset>
#include <cstdlib>
#include <ctime>
using namespace std;

#define lson l, mid, rt << 1
#define rson mid + 1, r, rt << 1 | 1
typedef long long ll;
const int N = 2e2 + 10;
const int INF = 0x3f3f3f3f;
const int MOD = 1e9 + 7;
const double eps = 1e-6;
struct Point	{
	int x, y, t, v;
	bool operator < (const Point &r) const	{
		if (y * r.x == x * r.y)	return y < r.y;
		else	return y * r.x < x * r.y;
	}
	bool operator == (const Point &r) const	{
		return y * r.x == x * r.y;
	}
}p[N];
int dp[40010];
vector<Point> block[N];

int main(void)    {
	int n, T, cas = 0;
	while (scanf ("%d%d", &n, &T) == 2)	{
		for (int i=1; i<=n; ++i)	{
			scanf ("%d%d%d%d", &p[i].x, &p[i].y, &p[i].t, &p[i].v);
		}
		sort (p+1, p+1+n);

		int cnt = 0;
		for (int i=1; i<=n; ++i)	block[i].clear ();
		block[++cnt].push_back (p[1]);
		for (int i=2; i<=n; ++i)	{
			if (p[i] == p[i-1])	block[cnt].push_back (p[i]);
			else	block[++cnt].push_back (p[i]);
		}
		for (int i=1; i<=cnt; ++i)	{
			for (int j=1; j<block[i].size (); ++i)	{
				block[i][j].t += block[i][j-1].t;
				block[i][j].v += block[i][j-1].v;
			}
		}

		memset (dp, 0, sizeof (dp));
		for (int i=1; i<=cnt; ++i)	{
			for (int j=T; j>=0; --j)	{
				for (int k=0; k<block[i].size (); ++k)	{
					if (j >= block[i][k].t)
						dp[j] = max (dp[j], dp[j-block[i][k].t] + block[i][k].v);
				}
			}
		}

		printf ("Case %d: %d\n", ++cas, dp[T]);
	}

    return 0;
}

  

时间: 2024-10-14 17:07:43

01背包(分组) HDOJ 4341 Gold miner的相关文章

【HDOJ】4341 Gold miner

分组01背包.在一条直线上的点归为一组. 1 /* 4341 */ 2 #include <iostream> 3 #include <sstream> 4 #include <string> 5 #include <map> 6 #include <queue> 7 #include <set> 8 #include <stack> 9 #include <vector> 10 #include <de

HDU 4341 Gold miner(分组背包)

http://acm.hdu.edu.cn/showproblem.php?pid=4341 题意: 一个人在原点(0,0)抓金子,每块金子是二维坐标平面的一个点(x,y)且y>0. 每块金子有一个价值v和获得需要的时间t.如果多个金子在一条从原点射出的直线上,那只能先抓近的,再抓远的.求在给定时间T下,所能获得的最大价值. 分析: 首先想想如果所有点都不共线是什么情况? 就是在给定时间T内要获取最大的价值和的点, 且所有点都可以任意选取. 那么这就是一个01背包问题. 不过如果存在共线的点,那

HDU 4341 Gold miner 分组背包变形

题意: 挖金矿,人在(0,0)点 n个金子 游戏时间为T 下面n行 (x, y) cost val 且若人 和 多块金子共线时,只能先取最近的金子,依次取,就是和游戏一样的. 且所有点只在1 2象限 思路: 我们先把所有共线的点分组 对于每组的物品,我们都可以认为取这个物品的花费就是前面所有物品的花费总和,而价值就是前面所有物品的价值总和. 这样就能消除每组物品的先取后取的影响了,但有一个情况就是这组至多只能取一个物品,所以每个状态只能是取了这个物品后或者是原始状态. 用原始状态转移,然后和原始

Robberies 01背包变形 hdoj

在选择物品的时候,对每种物品i只有两种选择,即装入背包或不装入背包.不能讲物品i装入多次,也不能只装入物品的一部分.因此,该问题被称为0-1背包问题. 将小偷计划要偷的钱的总数作为背包的容量,然后每个银行的存款就作为各个物品的重量, 每个银行小偷的逃跑率就作为每个物品的价值,这样就转化为01背包问题了. 至于为什么不可以用题目给的被抓获的概率作为价值,是因为小偷被抓与否的计算方法, 不是将每个银行小偷被抓的概率相乘,概率论的基本知识,所以要以逃跑率作为价值. 定义数组 F[j]为偷到j万元的时候

HDU 4341 Gold miner

先把线按照距离原点的距离排序,然后用叉积把在同一条直线上的点放在一起, 把在同一条线上的点中的前i个点当成一个点就,就转化成了分组背包. 写if(kas++) putchar('\n') 居然PE了 #include<bits/stdc++.h> using namespace std; int N,T; const int maxn = 203; const int MAXT = 40005; struct Point { int x,y,t,v; }P[maxn]; bool vis[ma

hdoj 1203 I NEED A OFFER! 【另类01背包】【概率背包】

题意:... 策略:动态规划. 因为是求至少能得到一个offer的概率,那我们可以反着求,求得不到一个offer的概率,最后用1减去就好了. 代码: #include<string.h> #include<stdio.h> double dp[10010]; struct node{ int a; double b; }s[10010]; int main() { int n, m, i, j; while(scanf("%d%d", &n, &

HDU 3033 I love sneakers! (01背包+反分组背包)

题意:给你 n,m,k,表示有k种鞋子共n双,你有m的容量: 每双鞋子有容量p和价值v:问是否买全k种鞋子,若能在容量为m的情况下最多能买到鞋子的价值为多少: 每双鞋子只能买一次(01背包),每种鞋子至少买一种(分组背包:每组只能有一个)与传统分组背包的限制相反. 注意初始化!!! #include<cstdio> #include<stdlib.h> #include<string.h> #include<string> #include<map&g

【背包问题】0-1背包、完全背包、多重背包、混合三种背包、二位费用背包、分组背包

一.0-1背包问题 输入:第一行物品的个数n,第二行背包的质量m,随后n行每行给出每个物品的重量和价值,每种物品只有一个. 输出:背包可以达到的最大价值 样例输入: 5 10 1 5 2 4 3 3 4 2 5 1 样例输出: 14 动态规划的过程中需要逆序,因为如果不是逆序那么 当i=0的时候 f[0]=0; f[1]=max(f[1],f[1-w[0]]+v[0])=5; f[2]=max(f[2],f[2-w[0]]+v[0])=10; f[3]=max(f[3],f[3-w[0]]+v[

51 Nod 1007 正整数分组【类01背包】

1007 正整数分组 基准时间限制:1 秒 空间限制:131072 KB 分值: 10 难度:2级算法题 将一堆正整数分为2组,要求2组的和相差最小. 例如:1 2 3 4 5,将1 2 4分为1组,3 5分为1组,两组和相差1,是所有方案中相差最少的. Input 第1行:一个数N,N为正整数的数量. 第2 - N+1行,N个正整数. (N <= 100, 所有正整数的和 <= 10000) Output 输出这个最小差 Input示例 5 1 2 3 4 5 Output示例 1 题目链接