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;
}