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