hdu3433A Task Process( 二分dp)

链接

二分时间,在时间内dp[i][j]表示截止到第i个人已经做了j个A最多还能做多少个B

#include <iostream>
#include<cstdio>
#include<cstring>
#include<algorithm>
#include<stdlib.h>
#include<vector>
#include<cmath>
#include<queue>
#include<set>
using namespace std;
#define N 200000
#define LL long long
#define INF 0xfffffff
const double eps = 1e-8;
const double pi = acos(-1.0);
const double inf = ~0u>>2;
int a[55],b[55];
int dp[210][210];
int main()
{
    int n,i,j,t,x,y,g,kk=0;
    cin>>t;
    while(t--)
    {
        scanf("%d%d%d",&n,&x,&y);
        int minz = N;
        for(i = 1; i <= n ;i++)
        {
            scanf("%d%d",&a[i],&b[i]);
            minz = min(minz,a[i]*x+b[i]*y);
        }
        int low = 0,high = minz,mid;
        while(low<=high)
        {
            mid = (low+high)>>1;
            memset(dp,-1,sizeof(dp));
            for(i = 0 ; i <= x ; i++)
            {
                if(a[1]*i<=mid)
                dp[1][i] = (mid-a[1]*i)/b[1];
            }
            for(i = 2; i <= n ;i++)
            {
                for(j = 0 ;j <= x ;j++)
                    for(g = 0 ; g <= x-j ; g++)
                    {
                        if(mid<a[i]*j) break;
                        if(dp[i-1][g]==-1) break;
                        dp[i][j+g] = max(dp[i][j+g],(mid-a[i]*j)/b[i]+dp[i-1][g]);
                    }
            }
            if(dp[n][x]>=y)
            high = mid-1;
            else
            low = mid+1;
        }
        printf("Case %d: ",++kk);
        cout<<low<<endl;
    }
    return 0;
}
View Code

 

posted @ 2014-03-20 19:10  _雨  阅读(228)  评论(0编辑  收藏  举报