1. 程式人生 > >SWUST OJ 698(dp)

SWUST OJ 698(dp)

1000(ms) 65535(kb) 1006 / 2689

用2 臺處理機A 和B 處理n 個作業。設第i 個作業交給機器A 處理時需要時間i a ,若由機器B 來處理,則需要時間i b 。由於各作業的特點和機器的效能關係,很可能對於某些i,有ai >=bi,而對於某些j,j≠i,有aj < bj 。既不能將一個作業分開由2 臺機器處理,也沒有一臺機器能同時處理2 個作業。設計一個動態規劃演算法,使得這2 臺機器處理完這n個作業的時間最短(從任何一臺機器開工到最後一臺機器停工的總時間)。研究一個例項: (a1,a2,a3,a4,a5,a6)=(2,5,7,10,5,2);(b1,b2,b3,b4,b5,b6)=(3,8,4,11,3,4)。 對於給定的2 臺處理機A 和B處理n 個作業,找出一個最優排程方案,使2臺機器處理完這n 個作業的時間最短。

輸入

的第1行是1個正整數n<=200, 表示要處理n個作業。 接下來的2行中,每行有n 個正整數,分別表示處理機A 和B 處理第i 個作業需要的處理時間。

輸出

最短處理時間

樣例輸入

6
2 5 7 10 5 2
3 8 4 11 3 4

樣例輸出

15

思路:之前做過類似題目,這裡主要是dp將每個任務進行分配,然後再找總的最小時間。現在用dp[i][j]表示A機器花費時間大於等於j的前提下,任務i給B機器完成的最小時間。

顯然狀態轉移有當   j<a[i-1]時候應該分配給B機器完成,這時候dp[i][j]=dp[i-1][j]+b[i-1];列舉i的時候向後增大一位,因為後面一個的狀態只與前面一個有關。

而當j>=a[i-1]時候,考慮分配給A機器還是B機器,顯然dp[i][j]=min(dp[i-1][j-a[i-1]],dp[i-1][j]+b[i-1]);

#include<bits/stdc++.h>
using namespace std;
const int INF=0x3f3f3f;
const int maxn=300;
const int maxm=3000;
int dp[maxn][maxm];
//dp[i][j]表示第i個作業由A完成的時間不超過j的前提下B完成的最少時間。
int a[maxn],b[maxn];
int main()
{
    int n;
    while(~scanf("%d",&n))
    {
        int sum=0;
        for(int i=0; i<n; i++)
        {
            scanf("%d",&a[i]);
            sum+=a[i];
        }
        for(int i=0; i<n; i++) scanf("%d",&b[i]);
        memset(dp,0,sizeof(dp));
        for(int i=1; i<=n; i++)
        {
            for(int j=0; j<=sum; j++)//列舉需要的時間
            {
                if(j<a[i-1]) dp[i][j]=dp[i-1][j]+b[i-1];
                //j<a[i-1]時候交給B完成
                else dp[i][j]=min(dp[i-1][j-a[i-1]],dp[i-1][j]+b[i-1]);
                //j>=a[i-1]時候考慮給A完成還是B完成,給A完成時,B花費時間為dp[i-1][j-a[i-1]]
                //B完成時,B花費時間為dp[i-1][j]+b[i-1]
            }
        }
        //上面將所有工作分配完成,現在統計最少時間dp[n][i]為B完成時間,i為A完成時間
        int temp,ans=INF;
        for(int i=0; i<=sum; i++)
        {
            temp=max(dp[n][i],i);
            if(temp<ans) ans=temp;
        }
        printf("%d\n",ans);
    }
    return 0;
}