hdu2333-贪心,如何去后效性,背包太大怎么办,如何最大化最小值,从无序序列中发掘有序性质

补充一下我理解的中文题意。。

你要重新组装电脑。。电脑有一些部件。。
你的预算有b,b(1~1e9),有n个部件。。
每个部件有类型和名称以及价钱和质量
现在你要在不超过预算b的情况下。。
每个类型都买一个部件。。然后最终的质量由最小的质量决定
在此约束下问你在预算b之内能组装的最大的质量是多少
对每个部件价钱范围1e6,质量范围1e9

===============

由于钱和质量没有必然联系

所以我们不能直接从质量小的开始贪。。

也没法从质量大的开始贪吧。。因为你还要保证你的钱要够

按质量排序则钱是无序的。。这样反正不好处理。。其他的处理方法我还没有想到

所以说你要怎么搞呢。。

a1,b1,a2,b2,a3,b3

c1,d1,c2,d2,c3,d3

x1,y1,x2,y2,x3,y3

因为一旦你的钱固定的话。。对于每一个枚举的总钱数。。这里的钱数是固定的。。

也就是dp中离散的钱数。。每一个枚举的钱数状态来说。。钱是固定的。。

所以你第一种取不取。。会对后面造成影响。。因为总钱数少了。。

好像也不是太好dp,如果算前i种物品剩余钱数是j所能达到的最大的最小质量

我后来想算前i种物品能够达到质量q的最小钱数。。但是由于q很大不能离散。。所以不能dp?这个理由好像很牵强。。

我现在也不是太清楚离散化和dp之间是什么关系。。但是毫无疑问对于一些连续的问题dp解决不了

一种解法是说。。我们二分最后的质量q。。

之前我在纠结

如果大于等于q1的最便宜的所有零件的组合超过预算。。

大于等于q2(q2>q1)的最便宜的所有零件的组合却不超过预算
但是这是不存在的。。q单调增加时。。最便宜的价格也单调递增。。

价格虽然无序。。但随着有序性质质量的单调递增。。最小价格单调递增。。
我大概是表达这个意思。。

因为如果质量小,这意味着你的选择性更多(比质量大的),所以也就最小价格也就可能越小

所以我们来二分一下最小质量。。因为每次都取最便宜的部件。。所以说。。其总价格也是单调递增的,前面证过了。。

所以对于每次二分的结果。。对每种部件取大于等于这个结果的最便宜的部件。。最后check超不超过预算

超过就质量往左走。。不超过就往右走。。,最后就能求出大于等于q的最小预算 ,最后就能求出来大于等于q的最小预算在不超过总预算的

情况下所能达到的最大的q

按理说我的下标只能到2..因为一共3个元素。。

但是。。下标3,4却能访问。。不报越界。。其值是一个野值吧。。

这一点我们以后一定要注意。。

但是你如果程序一开始你就访问4.。就会停止运行。。

这个vector的trick一定要记好了。。

#include <iostream>
#include <cstdio>
#include <map>
#include <vector>
#include <cstring>
#include <algorithm>
using namespace std;
int n,b,cnt;
char op1[50];char op2[50];
struct node{int x,q;node(int x,int q):x(x),q(q){}};
typedef long long ll;
const int maxn=1e3+7;
vector<node> things[maxn];
int mxcheap[maxn][maxn];
bool cmp(node a,node b){return (a.q!=b.q)?a.q<b.q:a.x<b.x;}
void init(){int i;for(i=0;i<maxn;++i) things[i].clear();}
void Sort(){int i;for(i=0;i<cnt;++i) sort(things[i].begin(),things[i].end(),cmp);}
bool check(int key){int i;ll sum=0;
    for(i=0;i<cnt;++i){
        int left=0,right=things[i].size()-1,mid;
        while(left<=right){
            mid=(left+right)>>1;
            if(things[i][mid].q<key) left=mid+1;else right=mid-1;
        }
        if(right+1<things[i].size()&&things[i][right+1].q>=key) right++;
        if(left>things[i].size()-1) {
        return false;}
        sum+=mxcheap[i][right];
    }
    return (sum>b)?false:true;}
int main(){

    int t;scanf("%d",&t);
    while(t--){
        scanf("%d%d",&n,&b);init();
        int i,j,x,q,lq=-1,rq=-1;cnt=0;
        map<string,int> mp;
        for(i=0;i<n;++i){
            scanf("%s%s%d%d",op1,op2,&x,&q);
            if(!mp.count(string(op1))){
                mp[string(op1)]=cnt++;
            }
            things[mp[string(op1)]].push_back(node(x,q));
            rq=(rq==-1)?q:max(q,rq);
            lq=(lq==-1)?q:min(q,lq);
        }
        Sort();
        for(i=0;i<cnt;++i){
            mxcheap[i][things[i].size()-1]=things[i].back().x;
            for(j=things[i].size()-2;j>=0;--j){
                mxcheap[i][j]=min(things[i][j].x,mxcheap[i][j+1]);
            }
        }
        int left=lq,right=rq,mid,ans=-1;
        while(left<=right){
            mid=(left+right)>>1;
            if(check(mid)){left=mid+1;}
            else{right=mid-1;}
        }
        if(check(right+1)) right++;
        printf("%d\n",right);
    }
    return 0;
}

这里我犯了一个错。。那就是。。check中的二分写错了。。

即使写对了也不对。。因为。。我以为质量最接近q的价格最便宜。。这只是对所有等于q的东西来说。。

那么对于大于q的可能更加便宜。。所以我们这里需要预处理出每种部件的i~size的区间的最小值。。

二分得到边界即可。。但是对于二分来讲。。我们应当既考虑left>size-1(size是vector的size)

也要考虑left<0,比如要求第一个》=q的元素的下标。。这里如果全部大于key那么right会小于0,

你要判断right+1合不合法以免漏判,如果全部小于key那么right=size-1,而left=size,此时left

就越界了。。这是妥妥的无解。。一定要注意这一点

性质:任何无序序列的区间i~n的最值都是单调的

时间: 2024-10-11 13:42:07

hdu2333-贪心,如何去后效性,背包太大怎么办,如何最大化最小值,从无序序列中发掘有序性质的相关文章

【贪心专题】POJ 2456 Aggressive cows &amp;&amp; NYOJ 586 疯牛(最大化最小值 贪心+二分搜索)

链接: click here~~ 题意:农夫 John 建造了一座很长的畜栏,它包括N (2 <= N <= 100,000)个隔间,这些小隔间依次编号为x1,...,xN (0 <= xi <= 1,000,000,000). 但是,John的C (2 <= C <= N)头牛们并不喜欢这种布局,而且几头牛放在一个隔间里,他们就要发生争斗.为了不让牛互相伤害.John决定自己给牛分配隔间,使任意两头牛之间的最小距离尽可能的大,那么,这个最大的最小距离是什么呢? [解题

分享工作中遇到的问题积累经验 事务日志太大导致insert不进数据

原文:分享工作中遇到的问题积累经验 事务日志太大导致insert不进数据 分享工作中遇到的问题积累经验 事务日志太大导致insert不进数据 今天开发找我,说数据库insert不进数据,叫我看一下 他发了一个截图给我 然后我登录上服务器,发现了可疑的地方,而且这个数据库之前有一段经历 在月初的时候这个数据库曾经置疑过,启动不起来 Could not redo log record (163041:116859:5), for transaction ID (0:-1175226963), on

华为总裁任正非:允许小部分力量去颠覆性创新

华为总裁任正非:允许小部分力量去颠覆性创新 来源: 新浪科技   发布者:新浪科技 热度11票   [共0条评论][我要评论]时间:2015年3月12日 18:22 新浪科技讯 3月12日下午消息,华为公司总裁任正非2014年11月14日在内部战略务虚会上发表讲话.任正非指出,华为大多数产品还是重视延续性创新,同时允许有一小部分新生力量去颠覆性创新,探索性地“胡说八道”,想怎么颠覆都可以,但是要有边界. 任正非还表示,现在的华为是“针尖”战略,但在争夺高端市场的时候,千万不能把低端市场丢了.因为

【BZOJ3875】【Ahoi2014】骑士游戏 SPFA处理有后效性动规

广告: #include <stdio.h> int main() { puts("转载请注明出处[vmurder]谢谢"); puts("网址:blog.csdn.net/vmurder/article/details/44040735"); } 题解: 首先一个点可以分裂成多个新点,这样就有了图上动规的基础. 即f[i]表示i点被消灭的最小代价,它可以由分裂出的点们更新. 但是这个东西有后效性,所以我们用SPFA来处理它. spfa处理后效性动规 我

【前方高能】!后效性!

今天校内测 由于忽视了后效性的问题,很happy地爆炸了 然后就华华丽丽地炸掉了树形dp..AK→220 然后悲剧的想到因为没有消掉后效性而炸掉的dp题好像不是第一个了QAQ 所以这波就讲关于dp中消除后效性的问题 dp中有一个很重要的问题就要保证无后效性,在状态转移的过程中非常关键 简单说,后效性就是之后要求的决策不会对当前要求决策产生干扰 所以如果没有处理好后效性的问题,dp很有可能就是白写了 比较常见的就是迭代之类的问题 ,,今天就是在迭代的时候崩掉的 就以这题为例↓ 3.Nearby C

如果程序太大而不能在DOS下运行,怎样才能使它在DOS下运行呢?

如果你的程序因太大(超过640KB)而无法在DOS下运行,有两种办法可为该程序提供更多的内存.一种办法是使用覆盖管理程序(overlay manager).覆盖管理程序用来管理程序的模块,并根据需要把它们从磁盘中读入内存或从内存中删去.这样,即使你的程序有几兆字节那么大,仍然可以在 只有640KB可用内存的计算机上运行.一些高级的覆盖管理程序允许你对需要同时读入和删除的模块进行“编组”,这有助于你通过精心调整程序来改善它的性 能.其它一些稍差的覆盖管理程序不具备这种功能,因此使用它们时你无法通过

实现不了的250亿 苏宁众包画饼太大

苏宁近几年玩了太多噱头:将自己定位于"云商"大玩线上线下同步.咋咋呼呼的弄出一个无疾而终的开放平台.以及免费贴膜告示噱头来吸引眼球,似乎也在向业界和用户诉说着自己对未来规划的茫然. 就在这些噱头还未停歇之际,苏宁最近又开始炒作众包的概念,并大喊着要改变整个供应链模式.实现商业模式的深度变革的口号.并且还夸下海口,明年就能创造250亿元价值的"巨大"诺言.不过各位看官,可别被这些新潮.老套的概念忽悠得晕头转向,要知道对于现在的苏宁来说,这众包模式和250亿的目标或许注

心太大,难免自欺(转)

“达沃斯论坛期间,我和我的好朋友.美国前总统克林顿一起吃饭,并讨论了全世界如何携手战胜全球金融危机……”,这可是芮城钢自己说的.芮成钢的“朋友”可不止这一位,要么是总统,要么是首相,要么是首富.当他自称要代表亚洲向奥巴马提问时,那口气,中国的一个部长.省长.企业家根本就不配做他的朋友,根本就不值得他来提问.这就是心太大. 其实,芮成钢的身份只是央视一名记者. 他充其量就是一名英语流利.有才华的优秀记者.采访这些名人,就是工作平台赋予自己的本职工作.他误把自己的机会当作了自己的身份.这就像皇帝身边

Unity3D占用内存太大的解决方法

原文链接:http://www.cnblogs.com/88999660/archive/2013/03/15/2961663.html 最近网友通过网站搜索Unity3D在手机及其他平台下占用内存太大. 这里写下关于Unity3D对于内存的管理与优化. Unity3D 里有两种动态加载机制:一个是Resources.Load,另外一个通过AssetBundle,其实两者区别不大. Resources.Load就是从一个缺省打进程序包里的AssetBundle里加载资源,而一般AssetBund