SRM528 DIV1 1000pt
只能说是很好的一道题目~~1000pt似乎从来木有不好的。。。。
学到的最重要的一点是:It is often a handy tool to formalize the conditions in the problem.
还有,就是又学到了一个定理,关于二分图的: Hall's marriage theorem ——There is a perfect matching if and only if for each subset of the left side of the graph, the total number of neighbours of this subset in the right side of the graph is greater than or equal to the number of nodes in the subset.
仔细分析一下,P1和P2被用的次数是一样的,假定为S(就是合法的选择了S次);然后假设vector中第i个元素用P1 xi次,用P2 yi次,就可以发现二分S+DP的思路了~
#include <iostream>
#include <cstdio>
#include <cstring>
#include <vector>
#include <string>
using namespace std;
class ColorfulCookie{
public:
int dp[55][2010];
bool check(const vector <int> &ck, int P1, int P2, int S){
int n = ck.size();
memset(dp, -1, sizeof(dp));
dp[0][0] = 0;
for(int i = 1; i <= n; i++){
int p = i-1;
for(int j = 0; j <= S; j++){
for(int x = 0; x<=j && x*P1<=ck[p]; x++){
int y = min(S-x, (ck[p]-P1*x)/P2);
if(dp[i-1][j-x] != -1){
dp[i][j] = max(dp[i][j], dp[i-1][j-x]+y);
}
}
}
}
return dp[n][S] >= S;
}
int getMaximum(vector <int> cookies, int P1, int P2){
int l, r, mid, ans, n = cookies.size();
l = r = ans = 0;
for(int i = 0; i < n; i++) r += cookies[i] / P1;
while(l <= r){
mid = (l+r) >> 1;
if(check(cookies, P1, P2, mid)){
ans = mid;
l = mid+1;
}
else r = mid - 1;
}
return ans*(P1+P2);
}
};