第1部分 基礎算法(提高篇)--第1章 貪心算法-1430:家庭作業

1430:家庭作業

時間限制: 1000 ms 內存限制: 65536 KB

【題目描述】
老師在開學第一天就把所有作業都佈置了,每個作業如果在規定的時間內交上來的話纔有學分。每個作業的截止日期和學分可能是不同的。例如如果一個作業學分爲10,要求在6天內交,那麼要想拿到這10學分,就必須在第6天結束前交。

每個作業的完成時間都是隻有一天。例如,假設有7次作業的學分和完成時間如下:

作業號 1 2 3 4 5 6 7
期限 1 1 3 3 2 2 6
學分 6 7 2 1 4 5 1
最多可以獲得15學分,其中一個完成作業的次序爲2,6,3,1,7,5,4,注意可能d還有其他方法。

你的任務就是找到一個完成作業的順序獲得最大學分。

【輸入】
第一行一個整數N,表示作業的數量。

接下來N行,每行包括兩個整數,第一個整數表示作業的完成期限,第二個數表示該作業的學分。

【輸出】
輸出一個整數表示可以獲得的最大學分。保證答案不超過longint範圍。

【輸入樣例】
7
1 6
1 7
3 2
3 1
2 4
2 5
6 1
【輸出樣例】
15


本題和智力大沖浪類似,唯一不同的是本題要加上一步優化,防止超時。因爲是保證學分儘量多,所以先按學分從大到小排序,把作業在規定期限內儘量靠後排比如說我有三個作業[ 2 6 ] [ 2 5 ] [ 2 4 ]我把第一個作業安排到2 ,第二個作業安排到 1,那麼第三個作業就不用考慮了,因爲沒有辦法繼續佈置了,也就是1~work[ ].t 都已經排滿了,每個都需要for循環判斷,很浪費時間,會超時。那麼我們標記一個dislike,表示從1 ~ dislike都不可以安排作業了.

#include<iostream>
#include<cstdio>
#include<algorithm>
#include<cmath>
#include<cstring>
#include<string>
#include<queue>
#include<functional>
#define N 1000001
using namespace std;

int n,dislike;
long long ans;
bool vis[N],f[N];

struct node
{
    int t,w;
}work[N];

bool cmp(node x,node y)
{
    return x.w  > y.w ;
}

bool pd(int x)
{
    for(int i = work[x].t ;i >= 1;i--)
    {
        if(vis[i] == 0)
        {
            vis[i] = 1;
            return 1;
        }
    }
    dislike = work[x].t ;     //不可以繼續安排作業了
    return 0;
}

int main()
{
    scanf("%d",&n);
    for(int i = 1;i <= n;i++)
        scanf("%d%d",&work[i].t ,&work[i].w );
    sort(work+1,work+n+1,cmp);
    
    memset(vis,0,sizeof(vis));
    
    for(int i = 1;i <= n;i++)
    {
        if(work[i].t < dislike) continue;  //在1~dislike區間裏都不可以安排作業了
        if(pd(i)) ans += work[i].w ;
    }
    
    printf("%ld",ans);
    
    return 0;
}
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章