hdu 5887 搜索+剪枝

Herbs Gathering

Time Limit: 3000/1000 MS (Java/Others)    Memory Limit: 32768/32768 K (Java/Others)
Total Submission(s): 687    Accepted Submission(s): 145

Problem Description

Collecting one‘s own plants for use as herbal medicines is perhaps one of the most self-empowering things a person can do, as it implies that they have taken the time and effort to learn about the uses and virtues of the plant and how it might benefit them, how to identify it in its native habitat or how to cultivate it in a garden, and how to prepare it as medicine. It also implies that a person has chosen to take responsibility for their own health and well being, rather than entirely surrender that faculty to another. Consider several different herbs. Each of them has a certain time which needs to be gathered, to be prepared and to be processed. Meanwhile a detailed analysis presents scores as evaluations of each herbs. Our time is running out. The only goal is to maximize the sum of scores for herbs which we can get within a limited time.

Input

There are at most ten test cases.
For each case, the first line consists two integers, the total number of different herbs and the time limit.
The i-th line of the following n line consists two non-negative integers. The first one is the time we need to gather and prepare the i-th herb, and the second one is its score.

The total number of different herbs should be no more than 100. All of the other numbers read in are uniform random and should not be more than 109.

Output

For each test case, output an integer as the maximum sum of scores.

Sample Input

3 70
71 100
69 1
1 2

Sample Output

3

/*
hdu 5887 搜索+剪枝

problem:
01背包问题,只是里面的数据达到了1e9

solve:
先对所有的物品按贡献(w/v)进行排序, 当搜到第u个点时,第u+1个在剩下的贡献是最大的. 如果剩下空间的全部放
u+1物品都无法大于当前的答案,则剪去.

hhh-2016-09-20 20:25:42
*/
#pragma comment(linker,"/STACK:124000000,124000000")
#include <algorithm>
#include <iostream>
#include <cstdlib>
#include <cstdio>
#include <cstring>
#include <vector>
#include <map>
#define lson  i<<1
#define rson  i<<1|1
#define ll long long
#define clr(a,b) memset(a,b,sizeof(a))
#define key_val ch[ch[root][1]][0]
using namespace std;
const int maxn = 200100;
const int inf = 0x3f3f3f3f;
const ll mod = 1e9 + 7;

template<class T> void read(T&num)
{
    char CH;
    bool F=false;
    for(CH=getchar(); CH<‘0‘||CH>‘9‘; F= CH==‘-‘,CH=getchar());
    for(num=0; CH>=‘0‘&&CH<=‘9‘; num=num*10+CH-‘0‘,CH=getchar());
    F && (num=-num);
}
int stk[70], tp;
template<class T> inline void print(T p)
{
    if(!p)
    {
        puts("0");
        return;
    }
    while(p) stk[++ tp] = p%10, p/=10;
    while(tp) putchar(stk[tp--] + ‘0‘);
    putchar(‘\n‘);
}

struct node
{
    ll v,w;
} p[maxn];

bool cmp(node a,node b)
{
    return 1.0*a.w/a.v > 1.0*b.w/b.v;
}

ll ans = 0,lm;
int n;

bool can_more(int u,ll val,ll &ans,ll limit)
{
    ll t = limit/p[u+1].v + 1;
    if(val + p[u+1].w * t >= ans)
        return true;
    return false;
}

void dfs(int u,ll val,ll limit)
{
    if(val > ans)
        ans = val;
    if(limit <= 0)
        return ;
    if(u < n && can_more(u,val,ans,limit))
    {
        for(int i = u+1; i <= n; i++)
        {
            if(limit >= p[i].v)
                dfs(i,val + p[i].w,limit - p[i].v);
        }
    }
}

void init()
{

}

int main()
{
    init();
    while(scanf("%d%I64d",&n,&lm) != EOF)
    {
        for(int i =1; i <= n; i++)
        {
            read(p[i].v);
            read(p[i].w);
        }
        sort(p+1,p+n+1,cmp);
        ans =0 ;
        dfs(0,0,lm);
        print(ans);
    }
}

  

时间: 2024-09-30 11:40:22

hdu 5887 搜索+剪枝的相关文章

poj 1198 hdu 1401 搜索+剪枝 Solitaire

写到一半才发现可以用双向搜索4层来写,但已经不愿意改了,干脆暴搜+剪枝水过去算了. 想到一个很水的剪枝,h函数为  当前点到终点4个点的最短距离加起来除以2,因为最多一步走2格,然后在HDU上T了,又发现再搜索过程中,这个估价函数应该是递减的(贪心),再加上这个剪枝就过了. #include<iostream> #include<cstdio> #include<cstring> #include<string> #include<list> #

hdu 4848 搜索+剪枝 2014西安邀请赛

http://acm.hdu.edu.cn/showproblem.php?pid=4848 比赛的时候我甚至没看这道题,其实不难.... 但是说实话,现在对题意还是理解不太好...... 犯的错误: 1.floy循环次序写错, 2.搜索的时候,应该先判断i是不是可以搜(就是可不可能产生解),然后标记vis[i]=1,我二逼的先标记vis[i]=1,然后判断i是不是可搜,这样肯定会导致有些时候,cnt!=n 我的剪枝方法(2546MS AC): 搜下一个结点之前,确保时间小于所有的未访问的结点的

hdu 3448(搜索+剪枝)Bag Problem

题意: 给n(n<=40)个物品和背包的容量w以及背包能装的物品个数k,每个物品有一个重量,问在满足背包的限制的情况下最多可以装多少物品. 思路 做过类似的题目,第一反应就是爆搜每个物品的两个状态放和不放.2^40肯定不行,来剪枝吧. 先把物品从小到大排序.一个有效的剪枝就是,最大的k个物品的重量和小于w那么这个重量和就是答案了,也是搜索中比较极限的情况,避免了去做搜索. 这样可以水过了,几乎没跑时间.5S有点吓人的意思?. 或许可以出可以卡这种剪枝的数据? 复杂度: 反正几乎没跑时间2333.

hdu 5305 (搜索+剪枝)

题意:有n个人(n<=8),每个人有一定数量的朋友,而和朋友的关系是线上朋友或者线下朋友(只能是其中一种).问每个人的线上朋友数量都等于线下朋友数量的方法数有多少. 做法:建成一个图,如果边的数目是奇数或者有人的度数是奇数,那个方法数肯定是0.否则,我们可以将边进行染色.假设黑色代表两个人之间是线上朋友,白色代表两个人之间是线下朋友.那么要满足条件,必须全部边有一半被染色,并且对于每个人相连的边有一半被染色.我们可以取一半的边进行染色,然后判断是不是每个人的一半相邻边被染色.这样,耗时为C(14

【搜索剪枝】HDU 5469 Antonidas

通道 题意:给出1字母树,询问一字符串是否出现在该树中 思路:直接搜索剪枝,有人点分治?写了几发都T了..有人会了教我? 代码: #include <cstdio> #include <cstring> #include <algorithm> using namespace std; struct Edge { int v, nxt; Edge () { } Edge (int _v, int _n) { v = _v, nxt = _n; } }; const in

50道hdu基础搜索总结(转)

Dfs: 大部分是直接递归枚举,即求满足约束条件下的解,虽不用剪枝,但也需要代码能力. 练习递归枚举的题目: 1241       Oil Deposits (dfs的连通块个数) 1016       Prime Ring Problem 1584       蜘蛛牌(简单dfs,简单的剪枝,还有人用DP做(???)) 1426       Sudoku Killer(练习递归的好题目 or Dancing links(???)) 2510       符号三角形(打表题,写写打表程序还是不错

poj 1054 The Troublesome Frog (暴力搜索 + 剪枝优化)

题目链接 看到分类里是dp,结果想了半天,也没想出来,搜了一下题解,全是暴力! 不过剪枝很重要,下面我的代码 266ms. 题意: 在一个矩阵方格里面,青蛙在里面跳,但是青蛙每一步都是等长的跳, 从一个边界外,跳到了另一边的边界外,每跳一次对那个点进行标记. 现在给你很多青蛙跳过后的所标记的所有点,那请你从这些点里面找出 一条可能的路径里面出现过的标记点最多. 分析:先排序(目的是方便剪枝,break),然后枚举两个点,这两个 点代表这条路径的起始的两个点.然后是三个剪枝,下面有. 开始遍历时,

USACO/fence8 迭代加深搜索+剪枝

题目链接 迭代加深搜索思想. 枚举答案K,考虑到能否切出K个木头,那么我们当然选最小的K个来切. 1.对于原材料,我们是首选最大的还是最小的?显然,首选大的能够更容易切出,也更容易得到答案. 2.对于目标木头,我们是优先得到最大的还是最小的?显然,由于K个木头我们都要得到,那么当然先把最大的(最难得到的)先得到,这种搜索策略更优. 3.假设总原材料为all,前K个木头总和为sum,那么all-sum就是这一次切割过程中能[浪费]的最大数目.对于一个切剩下的原材料,若它比最小的目标木头还要小,则它

hdu 4109 dfs+剪枝优化

求最久时间即在无环有向图里求最远路径 dfs+剪枝优化 从0节点(自己增加的)出发,0到1~n个节点之间的距离为1,mt[i]表示从0点到第i个节点目前所得的最长路径 #include<iostream> #include<cstdio> #include<cstring> #include<string> #include<algorithm> #include<vector> using namespace std; const