動態規劃--項目安排

題目來源:網易有道2013年校園招聘面試二面試題

題目描述:

小明每天都在開源社區上做項目,假設每天他都有很多項目可以選,其中每個項目都有一個開始時間和截止時間,假設做完每個項目後,拿到報酬都是不同的。由於小明馬上就要碩士畢業了,面臨着買房、買車、給女友買各種包包的鴨梨,但是他的錢包卻空空如也,他需要足夠的money來充實錢包。萬能的網友麻煩你來幫幫小明,如何在最短時間內安排自己手中的項目才能保證賺錢最多(注意:做項目的時候,項目不能並行,即兩個項目之間不能有時間重疊,但是一個項目剛結束,就可以立即做另一個項目,即項目起止時間點可以重疊)。

輸入:

輸入可能包含多個測試樣例。
對於每個測試案例,輸入的第一行是一個整數n(1<=n<=10000):代表小明手中的項目個數。
接下來共有n行,每行有3個整數st、ed、val,分別表示項目的開始、截至時間和項目的報酬,相鄰兩數之間用空格隔開。
st、ed、value取值均在32位有符號整數(int)的範圍內,輸入數據保證所有數據的value總和也在int範圍內。

輸出:

對應每個測試案例,輸出小明可以獲得的最大報酬。

樣例輸入:
3
1 3 6
4 8 9
2 5 16
4
1 14 10
5 20 15
15 20 8
18 22 12
樣例輸出:
16
22


思路:

總共有n個項目,用倒推的思想,假設已經知道第n-1個項目中的最優解dp[n-1],如果要得到n個項目中的最優解dp[n],就需要比較添加了第n個項目之後是否會提高收益,而添加了第n個項目之後的解是,value[n] + dp[i],其中i是指添加了第n個項目之後,前i個項目可以不受影響的進行。

到了這一步,就可以知道需要對項目按照結束時間進行排序了,對吧?



#include <stdio.h>
#include <algorithm>
using namespace std;
int n;
class P{
public:
    int st,ed,value;
};
P p[10001];
int dp[10001]; //dp[i]安排前i個項目,多能到得到的最大value
bool cmp(const P & p1, const P & p2){
    return p1.ed < p2.ed;
}

int main(){
    int n, i, j;
    while(scanf("%d", &n) != EOF){
        for(i=1; i<=n; i++){
            scanf("%d %d %d", &p[i].st, &p[i].ed, &p[i].value);
            dp[i] = 0;
        }
        sort(p+1, p+n+1, cmp);
        dp[0] = 0;
        for(i=1; i<=n; i++){
            for(j=i-1; j>0; j--){
                if(p[i].st >= p[j].ed)
                    break;
            }
            dp[i] = dp[j] + p[i].value;
            if(dp[i] < dp[i-1])
                dp[i] = dp[i-1];
        }
        printf("%d\n",dp[n]);
    }
    return 0;
}


發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章