zoukankan      html  css  js  c++  java
  • 蛋糕分层

    【题目描述】

    蛋糕店刚好有对应上、中、下三层的三类蛋糕,大家知道多层蛋糕一般都是上层最小,中层其次,下层最大,不然蛋糕就不漂亮了。在知道每一种蛋糕的体积的前提下有多少符合条件的方案。 

    【思路分析】
    【不好的个人感觉】

    看到这道题,就感觉是动态规划,题目不是说蛋糕层数的要求吗?可以从下往上的推,个人的第二个感觉是一道搜索题,然后就这么打着,样例过的,手推的数据也过的。没想到就QAQ了。

    【暴力出奇迹

    爆0之后,试了一下暴力,把每一种情况都考虑一遍,选最优值,这样时间复杂度是O(n^2)的。至少还有点分(虽然我没提交,但我知道啊)。个人感觉就是不对。emm,我想复杂了。

    【计数】

    其实计数就是暴力的优化,读入把数字存入下标(万幸没有负数,哈哈)。数据卡的刚刚好。然后与暴力一样,不停地从上往下(只希望不要挂了),找最优值。啊,果然对了(AC)。这相当于是正解了吧。

    先附上代码:(此代码,不要copy谢谢)

    #include<bits/stdc++.h> // 万能头 
    using namespace std; // 空间定义 
    long long n,m,k,x,a[3939],b[3939],c[3939],maxn1,maxn2,maxn3,ans,a1[514514];//定义变量 
    int main() { //开始疯狂的操作 
    	cin>>n>>m>>k; // 读入这些值 
    	for(int i=1; i<=n; i++) {
    		cin>>x; //读入 
    		a[x]++; // 放入下标 
    		maxn1=max(maxn1,x);//取最大值 
    	}
    	for(int i=1; i<=m; i++) {
    		cin>>x; // 读入 
    		b[x]++; // 放入下标 
    		maxn2=max(maxn2,x); // 取最大值 
    	}
    	for(int i=1; i<=k; i++) {
    		cin>>x; // 读入 
    		c[x]++; // 放入下标 
    		maxn3=max(maxn3,x); // 取最大值 
    	}
    	for(int i=1; i<=max(maxn3,maxn2); i++)
    		c[i]=c[i-1]+c[i]; // 前缀处理 ,类似 dp 
    	for(int i=1; i<=max(maxn1+1,maxn2+1); i++)
    		a1[i]=a1[i-1]+a[i-1]; // 前缀处理 ,类似dp 
    	for(int i=1; i<=maxn2; i++)
    		ans+=(c[maxn3]-c[i])*b[i]*a1[i]; // 不停累积最优值 
    	cout<<ans<<endl; // 输入 
    	return 0; // 好习惯,别忘记了 
    }//End; 
    

      

    【正解】

    老师后来讲了这道题目,原来正解是二分,我恍然大悟(我那个时候为啥没有想到呢?)。

    我知道你们对二分有点糊涂。

    我来给你们讲一讲。

    二分

    二分查找也称折半查找(Binary Search),它是一种效率较高的查找方法。但是,折半查找要求线性表必须采用顺序存储结构,而且表中元素按关键字有序排列。

    二分查找对这道题没有用,我们解决这道题的话,要用二分答案。

    【二分答案】

    【定义】

    二分答案与二分查找类似,即对有着单调性的答案进行二分,大多数情况下用于求解满足某种条件下的最大(小)值。

    • 何时可以使用“二分答案”

        不是任何题目都适合使用“二分答案”的,我Sam观察到一般有以下的一些特征:

    • A. 候选答案必须是离散的 ,且已知答案的范围是:[最小值min, 最大值max] (连续区间上不能进行二分操作)
    • B. 候选答案在区间[min,max]上某种属性一类一类的排列 (这样就能在此属性上进行二分操作 ),各个类别不交错混杂

    【模板说明】

    一定要先排序。

    可以把答案看成key , 一旦当前这个序列中的数(我是根据从小到大排序的)大于key ,则右端点(r)要等于中间值(我取中间值为(l+r)>> 1).否则就取左端点(l)要等于中间值。

    从大到小同理.

     

    【二分模板代码】(不同人写法不同)(这是我的模板)

    int check(int key){
        int l = 1,r = n;
        int mid;
        while(l<=r){
            mid = (l+r) >> 1;
            if(key > a[mid]) l = mid+1;
            else if(key < a[mid])r = mid-1;
            else return 1;
        }
        return 0;
    }
    

      

    介绍算法结束!

     

    【将二分融入题目之中】

    二分答案的使用可以在查找蛋糕的最优值时候使用。

    其他一样。

    代码就不放了。自己思考。。。。

    End!

  • 相关阅读:
    《人月神话》读后感
    十天冲刺计划(第二次)
    日历表的事件处理和管理(刘静)
    十天冲刺计划
    结组开发项目(TD学生助手)
    电梯调度(二)
    敏捷软件开发方法综述
    对于二维数组求子数组的和的最大值
    电梯调度(一)
    FloatyFish休闲游戏 Beta正式发布
  • 原文地址:https://www.cnblogs.com/wangshengjun/p/10926206.html
Copyright © 2011-2022 走看看