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; } }