poj1973

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 long
const 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 , 1
int 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 ;
}
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章