一本通網站 1430:家庭作業


原題  傳送門

【題目描述】

老師在開學第一天就把所有作業都布置了,每個作業如果在規定的時間內交上來的話才有學分。每個作業的截止日期和學分可能是不同的。例如如果一個作業學分為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

 

第一眼看這個題,和智力大沖浪有點像,甚至還比那個題簡單些,不用判斷做不完怎么辦。

貪心策略:

為了使學分盡可能的多,我們要盡可能得做學分多的作業,我們先按照學分從大到小排序,然后枚舉每一個作業,盡量讓這個作業貼着期限完成;

我們可以從某一個作業的期限往前找,若找到沒安排作業的時間點就將它安排上。

代碼如下:

#include<iostream>
#include<cstdio>
#include<algorithm>
using namespace std;
struct homework
{
    int k,date;
}a[1000001];
int read()
{
    char ch=getchar();
    int a=0,x=1;
    while(ch<'0'||ch>'9')
    {
        if(ch=='-') x=-x;
        ch=getchar();
    }
    while(ch>='0'&&ch<='9')
    {
        a=(a<<3)+(a<<1)+(ch-'0');
        ch=getchar();
    }
    return a*x;
}
int cmp(homework x,homework y)
{
    return x.k>y.k;              //按照學分從大到小排序 
}
int n,sum,hash[1000001];
int main()
{
    n=read();
    for(int i=1;i<=n;i++)
    {
        a[i].date=read();
        a[i].k=read();
    }
    sort(a+1,a+1+n,cmp);
    for(int i=1;i<=n;i++)
    {
        int bj=1;
        for(int j=a[i].date;j>=1;j--) //盡量讓作業貼着期限做,來減少對其他作業的影響 
        {
            if(hash[j]==0)
            {
                hash[j]=1;
                bj=0;
                sum+=a[i].k;
                break;
            }
        }
    }
    cout<<sum<<endl;
    return 0;
}

但是將這份代碼交上去后我們發現有兩個點TLE了!我們要進一步優化!

如果我們對某一個作業 i 進行安排,發現從a[i].date枚舉到1它們的hash都為1,也就是說:從1~a[i].date都已經安排滿了,安排不了其他的作業了;

我們可以用q來記錄這個a[i].date,對於后面的作業,如果它的期限a[i+1].date<=q,說明這個作業一定安排不了,我們直接跳出就好了,不用再枚舉了;

AC代碼如下:

#include<iostream>
#include<cstdio>
#include<algorithm>
using namespace std;
struct homework
{
    int k,date;
}a[1000001];
int read()
{
    char ch=getchar();
    int a=0,x=1;
    while(ch<'0'||ch>'9')
    {
        if(ch=='-') x=-x;
        ch=getchar();
    }
    while(ch>='0'&&ch<='9')
    {
        a=(a<<3)+(a<<1)+(ch-'0');
        ch=getchar();
    }
    return a*x;
}
int cmp(homework x,homework y)     //按照學分從大到小排序 
{
    return x.k>y.k;
}
int n,sum,q,hash[1000001];
int pan(int x)
{
    for(int i=a[x].date;i>=1;i--)
    {
        if(hash[i]==0) 
        {
            hash[i]=1;
            return 1;
        }
    }
    q=a[x].date;                   //如果到了這里,說明1~a[x].date已經安排滿了,用q記錄下來 
    return 0;
}
int main()
{
    n=read();
    for(int i=1;i<=n;i++)
    {
        a[i].date=read();
        a[i].k=read();
    }
    sort(a+1,a+1+n,cmp);
    for(int i=1;i<=n;i++)
    {
        if(a[i].date<q) continue; //直接跳出,節省時間 
           if(pan(i)) sum+=a[i].k;    
    }
    printf("%d\n",sum);
    return 0;
}

 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM