poj1973

来源:互联网 发布:中国seo排行榜 编辑:程序博客网 时间:2024/06/05 15:25

poj1973

题目链接
题意是有n个人,有项目A和项目B,项目A和B总共有m个,它们分别相互独立.每个人完成一个项目A,B的时间分别是xi,yi.问完成m个A项目和m个B项目所需要的时间是多少.
我们很容易想要用二分时间,但是check函数并不好想,听有的dalao说用一种贪心的方法,先按b从小到大排序,如果相等则a从大到小排序.然后从后往前,也就是说让做b慢的先去把A做了,做到m个后再从前往后,让做b快的,去把b做了.这个贪心策略好像没什么问题…….因为如果这个时间内能把A做完,那么无论怎么安排,A总能被做完,然后再在A被做完的基础上,把做b最快的那一批挑出来.这个做法有点类似背包问题的贪心解法,实际上是错的.当我们让某个人把时间做优先A项目时,有可能余出来的时间没办法做B,但实际上他可以少做一些A项目,去做B项目,类似于背包问题.
再考虑用dp,因为这个时间有点大,我们比较难像背包一样写进状态里,于是我们可以令dp[i][j]为前i个人做了j个A项目时最多可以做多少个B项目,方程是
dp[i][j] = max(dp[i-1][k ] + (time - (j -k) * a[i] ) / b[i]) ( 0<=k <= j)

#include<cmath>#include<algorithm>#include<cstring>#include<string>#include<set>#include<map>#include<time.h>#include<cstdio>#include<vector>#include<list>#include<stack>#include<queue>#include<iostream>#include<stdlib.h>using namespace std;#define  LONG long longconst LONG  INF=0x3f3f3f3f;const LONG  MOD=1e9+ 7;const double PI=acos(-1.0);#define clrI(x) memset(x,-1,sizeof(x))#define clr0(x) memset(x,0,sizeof x)#define clr1(x) memset(x,INF,sizeof x)#define clr2(x) memset(x,-INF,sizeof x)#define EPS 1e-10#define lson  l , mid , rt<< 1#define rson  mid + 1 ,r , (rt<<1)+1#define root 1, m , 1int dp[120][120] ;int a[120] , b[120] ;int n ,m ;int check(int time ){    clr2(dp) ;    dp[0][0] = 0 ;    for(int i = 1; i<= n ; ++ i)    {        for(int j = 0 ; j <= m ; ++j)        {            for(int k = 0 ; k <= j ; ++ k)            {                if(time - (j - k) * a[i] >= 0 && dp[i-1][k] > -100)                dp[i][j] = max(dp[i][j] , dp[i-1][k] + ( time - (j - k) * a[i] ) /b[i] ) ;            }        }    }    if(dp[n][m] >= m)    return 1 ;    else return 0 ;}int main(){    int T ;    cin >> T;    while(T --)    {        cin >> n >> m ;        for(int i = 1 ; i <= n ; ++i)            cin>>a[i]>>b[i] ;        int l = 0  , r = 1000000 ;        int mid  ;        while(l < r)        {            mid = (l + r ) / 2;            if(check(mid))            {                r = mid ;            }            else l = mid + 1;        }        cout<<l<<endl ;    }    return 0 ;}