HDU 4341

分组背包而已。注意的是,每个时间T,要把一组的全加进去比较一次。

#include <iostream>
#include <cstdio>
#include <cstring>
#include <algorithm>
#include <vector>
#define N 205
#define T 41000

using namespace std;

int dp[T];
struct node{
	int x,y;
	int t,v;
}Node[N];
struct zu{
	int t,v;
	zu(int tt,int vv){
		t=tt; v=vv;
	}
};
vector<zu>pts[N];

bool cmp(node a,node b){
	if(a.x*b.y-a.y*b.x>0)
	return true;
	else if(a.x*b.y-a.y*b.x==0){
		if(a.x*a.x+a.y*a.y<b.x*b.x+b.y*b.y)
		return true;
	}
	return false;
}

int main(){
	int n,t,kase=0;
	while(scanf("%d%d",&n,&t)!=EOF){
		for(int i=0;i<n;i++){
			scanf("%d%d%d%d",&Node[i].x,&Node[i].y,&Node[i].t,&Node[i].v);
			pts[i].clear();
		}
		pts[n].clear();
		sort(Node,Node+n,cmp);
		int al=1;
		pts[al].push_back(zu(Node[0].t,Node[0].v));
		for(int i=1;i<n;i++){
			if(Node[i].x*Node[i-1].y-Node[i].y*Node[i-1].x!=0)
			al++;
			pts[al].push_back(zu(Node[i].t,Node[i].v));
		}
		for(int i=1;i<=al;i++){
			int size=pts[i].size();
			for(int k=1;k<size;k++){
				pts[i][k].t+=pts[i][k-1].t;
				pts[i][k].v+=pts[i][k-1].v;
			}
		}
		memset(dp,0,sizeof(dp));
		for(int i=1;i<=al;i++){
			int size=pts[i].size();
			for(int p=t;p>=0;p--)
			for(int k=0;k<size;k++){
				if(p-pts[i][k].t<0) break;
				dp[p]=max(dp[p],dp[p-pts[i][k].t]+pts[i][k].v);
			}
		}
		printf("Case %d: %d\n",++kase,dp[t]);
	}
	return 0;
}

  

时间: 2024-11-08 17:24:36

HDU 4341的相关文章

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 分组背包

B - Gold miner Time Limit:2000MS Memory Limit:32768KB     Description Homelesser likes playing Gold miners in class. He has to pay much attention to the teacher to avoid being noticed. So he always lose the game. After losing many times, he wants you

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

HDU 4341 Gold miner 分组背包变形

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

背包问题总结二

上一篇总结了三种基本的背包类型,但做题时很少让直接赤裸裸的求某一种背包.由它们延伸出来的问题可能更加重要. 但只要理解了基本的三种背包,对于更加复杂的问题的理解也不是很难. 仍然参考背包九讲的内容. 混合三种背包 将三种背包混合起来,就是说有的物品只有一件,有的物品有无限件,而有的物品有n[i]件.求把物品装入背包不超过背包容量的最大价值. 听起来很高大上,其实把它们分别开来,对不同类型的问题进行相应的背包即可.. for(int i = 1; i <= N; i++) { if(第i件物品属于

2012 #5 Gold miner

Gold miner Time Limit: 4000/2000 MS (Java/Others)    Memory Limit: 32768/32768 K (Java/Others)Total Submission(s): 1889    Accepted Submission(s): 740Time Limit:2000MS     Memory Limit:32768KB     64bit IO Format:%I64d & %I64u Submit Status Practice 

hdu Phone List 字典树的前缀判断

题链:http://acm.hdu.edu.cn/showproblem.php?pid=1671 Phone List Time Limit: 3000/1000 MS (Java/Others)    Memory Limit: 32768/32768 K (Java/Others) Total Submission(s): 12763    Accepted Submission(s): 4341 Problem Description Given a list of phone numb

HDU 6203 ping ping ping [LCA,贪心,DFS序,BIT(树状数组)]

题目链接:[http://acm.hdu.edu.cn/showproblem.php?pid=6203] 题意 :给出一棵树,如果(a,b)路径上有坏点,那么(a,b)之间不联通,给出一些不联通的点对,然后判断最少有多少个坏点. 题解 :求每个点对的LCA,然后根据LCA的深度排序.从LCA最深的点对开始,如果a或者b点已经有点被标记了,那么continue,否者标记(a,b)LCA的子树每个顶点加1. #include<Bits/stdc++.h> using namespace std;

HDU 5542 The Battle of Chibi dp+树状数组

题目:http://acm.hdu.edu.cn/showproblem.php?pid=5542 题意:给你n个数,求其中上升子序列长度为m的个数 可以考虑用dp[i][j]表示以a[i]结尾的长度为j的上升子序列有多少 裸的dp是o(n2m) 所以需要优化 我们可以发现dp的第3维是找比它小的数,那么就可以用树状数组来找 这样就可以降低复杂度 #include<iostream> #include<cstdio> #include<cstring> #include