TopCoder-SRM635-DIV1-250pt-ShoppingSurveyDiv1-二分搜索

http://community.topcoder.com/stat?c=problem_statement&pm=13455&rd=16077

这道题目很容易往贪心的方向思考。其实很难找到一个贪心策略正确的求出最少的>=K的顾客数目。

考虑到答案是求顾客的数目,而这个数目的范围是[0,n),并且n并不是很大。所以可以在解空间进行二分搜索。每次假定一个解x个顾客>=k。

当进行这样的假定时,就只需要检查在x个>k的顾客购买了最大可能的物品之后,余下的物品是否能够被余下的顾客数目在满足每个顾客<k的情况下被满足。

x个顾客>k时,我们可以用贪心法假定每个顾客都买了最多数目的物品,把这些物品从s[]中减去后,得到一个新数组。

于是现在的问题就是n-x个顾客,能否在每个顾客都购买<k个物品的情况下,得到s'[]所描述的评价。

简单的分析后,发现只要满足两个条件:

1) (n-x)>=max{s'[i]} 最大数量的那个物品能够被指派给顾客。

2)(n-x)*(k-1) >=sum(s'[i]),可以通过组合使得每个顾客的指派都指派到没有被指派的物品。

由此就能得到答案。

            vector<int> s;
            int K;
            bool Check(int x){
                vector<int> cs=s;
                for(int i=0;i<m;i++) cs[i]=max(0,cs[i]-x);
                int maxv=cs[m-1];
                int acc=accumulate(cs.begin(),cs.end(),0);
                int left=n-x;
                if ((n-x)*(K-1)>=acc && left>=maxv) return true;
                return false;
            }
        int minValue(int N, int K, vector <int> s) 
            { 
                n=N;
                m=s.size();
                this->K=K;
                sort(s.begin(),s.end());
                this->s=s;
                int l=0;
                int r=N;
                while(l<r){
                    int mid=(l+r)/2;
                    if(Check(mid)) r=mid;
                    else l=mid+1;
                }
                return l;
            }
}

 

posted @ 2014-10-24 19:31  zombies  阅读(220)  评论(0编辑  收藏  举报