P1280 尼克的任務(資源分配類動態規劃)

傳送門

題解:這題顯然是一個線性動規,那麼肯定是第一時間想到設f[i]:1~i的最大空閒時間,但是,想了一下之後發現,第i時刻的最大空閒時間是和後面i+選擇任務的持續時間的時刻有關係的,那麼,正着找肯定是不行的,我們來試一下倒着搜,即設f[i]表示i~n的最大空閒時間,經嘗試,發現是完全可行的,可以列出動態轉移方程如下

(本時刻無任務)f[i]=f[i+1]+1;//繼承上一個時刻的最大空閒時間後+1

(本時刻有任務)f[i]=max(f[i],f[i+a[sum])//a[sum]表示在這個時刻的任務的持續時間,找出選擇哪一個本時刻任務使空閒時間最大化

那麼既然是倒着搜,從後往前的任務對應的開始時間自然也要反過來,從大到小排序(同時也是爲了把相同開始時間的任務放到一起),當然在進行狀態刷新的時候別忘了拿sum不斷計一下已經到哪一個任務了


#include<bits/stdc++.h>

using namespace std;

typedef long long ll;

const int maxn=10001;

ll sum[maxn],dp[maxn];

struct ren
{
    ll ks,js;
};
ren z[maxn];

bool cmp(ren a,ren b)
{
    return a.ks>b.ks;
}

int main()
{
    ll n,k;
    cin>>n>>k;
    for(int i=1;i<=k;i++){
        cin>>z[i].ks>>z[i].js;
        sum[z[i].ks]++;
    }
    sort(z+1,z+k+1,cmp);
    ll num=1;
    for(int i=n;i>=1;i--){
        if(sum[i]==0){
            dp[i]=dp[i+1]+1;
        }else{
            for(int j=1;j<=sum[i];j++){
                if(dp[i+z[num].js]>dp[i]){
                    dp[i]=dp[i+z[num].js];
                }
                num++;
            }
        }
    }
    cout<<dp[1]<<endl;
    return 0;
}

 

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