1. 程式人生 > >dp 優化 F2. Pictures with Kittens (hard version)

dp 優化 F2. Pictures with Kittens (hard version)

dp的優化可能是自己的弱項吧

F1中n*n*n的複雜度強行過去了 

F2就無能為力了;

狀態轉移

dp[ i ] [ j ] 第一個i存的是位置  1-n;    j是放入數字的個數   然後F1就暴力過去了

#include<bits/stdc++.h>
#define int long long
using namespace std;
const int maxn=5000+10;
int dp[maxn][maxn];
int a[maxn];
int32_t main()
{
    int n,k,x; cin>>n>>k>>x;
    
for(int i=1;i<=n;i++) cin>>a[i]; dp[0][0]=0; for(int i=1;i<=n;i++) { //cout<<" "<<i<<endl; //cout<<" "<<i-k+1<<endl; for(int j=i-k;j<i;j++) { if(j<0) continue; for(int q=(i-1)/k;q<x;q++) {
if(dp[j][q]||i<=k) dp[i][q+1]=max(dp[i][q+1],dp[j][q]+a[i]); } } } int maxn=0; for(int i=n;i>=n-k+1;i--) { maxn=max(dp[i][x],maxn); } if(maxn) cout<<maxn<<endl; else cout<<-1<<endl; }
暴力的F1

然後F2  gg了

看了別人的程式碼  大致有幾種寫法

雙端佇列優化   deque<pair<int,int> >  de[maxn];

寫的不難懂點   de[  ]  [  ]  [   ]  大致就是這樣存的  de[ ] 這個表示的是 存的數字個數  第二個括號存的是 第i個位置j個數的最大值; 第三個括號存的是  位置 

第i個位置是由 前[ i-k,i-1 ]位置的地方轉移過來的;

從  de[j]  到 de[j+1]   必須確定  de[j+1] 已經轉移了  所以第二層轉移就是   j=x-1; j>=0;j--; 

#include<bits/stdc++.h>
#define int long long
using namespace std;
const int maxn=5e3+10;
int a[maxn];
deque<pair<int,int> >  de[maxn];
int32_t main()
{
    //priority_queue(int,vector<int>,greater<int>) qu;
    int n,k,x; cin>>n>>k>>x;
    for(int i=1;i<=n;i++) cin>>a[i];
    int ans=-1;
    de[0].push_back({0,0}) ; // first  cun zhi  second  pos;
    for(int i=1;i<=n;i++)
    {
        for(int j=x-1;j>=0;j--)
        {
            while(!de[j].empty() && de[j].front().second<i-k )  de[j].pop_front(); // i-k
            if(de[j].empty()) continue;
            int val=de[j].front().first+a[i];  // jia shang zhe ge shu
            while(!de[j+1].empty() && de[j+1].back().first <=val )  de[j+1].pop_back();
            de[j+1].push_back({val,i});  // di i  ge wei zhi j+1 ge shu he zui da
            if(j+1==x&&i+k>n)
            {
                ans=max(val,ans);
            }
        }
    }
    cout<<ans<<endl;

}
看的懂的程式碼