zoukankan      html  css  js  c++  java
  • 关于二分法中取中间值时向下和向上取整的问题(由大白LA3971想到的)

    最近在做刘汝佳的大白,有一道题目LA_3971,也是UVA_12124,是用二分法做的。

    题目地址:http://uva.onlinejudge.org/index.php?option=com_onlinejudge&Itemid=8&category=456&page=show_problem&problem=3276代码如下

    /*************************************************************************
        > File Name: 12124.cpp
        > Author: BobLee
        > Mail: wustboli@gmail.com 
        > Created Time: Mon 25 Mar 2013 08:36:44 PM CST
     ************************************************************************/
    
    #include<iostream>
    #include<cstdio>
    #include<cstring>
    #include<cmath>
    #include<algorithm>
    #include<vector>
    #include<map>
    #include<string>
    using namespace std;
    
    const int maxn = 1010;
    
    struct co
    {
    	int price;
    	int qua;
    };
    
    map<string,int> id;
    vector<co> com[maxn];
    int N,B;
    int cnt;
    
    int ID(string s)
    {
    	if(!id.count(s))
    		id[s] = cnt++;
    	return id[s];
    }
    
    bool fun(int q)
    {
    	int sum = 0;
    	for(int i=0;i<cnt;i++)
    	{
    		int cheap = B+1;
    		int m = com[i].size();
    		for(int j=0;j<m;j++)
    		{
    			if(com[i][j].qua>=q)
    				cheap = min(cheap,com[i][j].price);
    		}
    		if(cheap > B)
    			return false;
    		sum+=cheap;
    		if(sum>B)
    			return false;
    	}
    	return true;
    }
    
    int main()
    {
    #ifndef ONLINE_JUDGE
    	freopen("in.txt","r",stdin);
    #endif
    	int t;
    	scanf("%d",&t);
    	while(t--)
    	{
    		scanf("%d%d",&N,&B);
    		char type[30],name[30];
    		int price,quaa;
    		int maxq = 0;
    		cnt=0;
    		for(int i=0;i<N;i++)
    			com[i].clear();
    		for(int i=0;i<N;i++)
    		{
    			scanf("%s%s%d%d",type,name,&price,&quaa);
    			maxq = max(maxq,quaa);
    			com[ID(type)].push_back((co){price,quaa});
    		}
    		int L=0;
    		int R=maxq;
    		while(L<R)
    		{
    			int M=(L+R+1)/2;
    			//cout<<L<<"  "<<R<<" "<<M<<endl;
    			if(fun(M))
    			{
    				L=M;
    			}
    			else
    				R=M-1;
    			//cout<<L<<"  "<<R<<" "<<M<<endl;
    			//getchar();
    		//	if(M==0)
    		//		break;
    		}
    		printf("%d\n",L);
    	}
    	return 0;
    
    }
    
    

    可以看到我取中值的时候,用的是向上取整。(实际上是刘汝佳这么写的)

    我当时写的是  M=(L+R)/2;   也就是向下取整的意思,但是在不同提交的遇到了一个问题。

    我的TLE了。

    当时我是百思不得其解,后来仔细思考了之后发现了一个问题。那就是你在这个程序中是求一个合理区间的最大值。

    举个例子,假如我们的最后要取的值为5,区间也是[0,5],用向下取整的话

    LR M

    0 5 2

    25 3

    35 4

    45 4

    45 4

    。。。

    发现问题了吧,这个时候就会陷入死循环。

    再来一个例子,假如我们是求一个合理区间的最小值,二分的代码

    while(L<R)
    {
            M=(L+R+1)/2;
            if(ok(M))
                  R=M;
            else
                  L=M+1;
    }

    我们还是用向上取整来做。区间为[0,5],最后的值为0

    LR M

    0 5 3

    03 2

    02 1

    0 1 1

    01 1

    。。。

    又陷入了死循环,但是我们可以发现如果这时用向下取整就是可行的了。

    所以由上面就可以得出,

    当我们使用二分法求某个合理区间最值的时候,我们要十分注意两个端点的极端值的情况。

    当然还有一种更保险的方法

    那就是不用上面的二分的方法

    在二分的时候用另外一个变量来记录合理值,然后L=M+1  OR  R=M-1

    所以这样的话是不回陷入到死循环里面去的

    这就是我由这T想到了,好久不写博客了。还是要捡起来啊。


  • 相关阅读:
    83. Remove Duplicates from Sorted List
    141. Linked List Cycle
    hdu1028 划分数
    XDU1019 阶乘因子的个数
    poj2773 容斥原理
    poj1091 容斥原理的应用
    poj1173 多重集组合数
    HDU 1465 错排问题
    poj 1496
    复习之求一个数的约束之积模一个质数
  • 原文地址:https://www.cnblogs.com/javawebsoa/p/2985652.html
Copyright © 2011-2022 走看看