令人困惑的dp逻辑

时间:2017-01-11 20:17:45

标签: c++ algorithm dynamic-programming

我正在尝试解决hackerearth上的动态编程问题。 即使在尝试使用笔和纸模拟逻辑之后,我也无法理解解决方案(在editorial中给出)。 有人可以解释评论的行吗?任何帮助将不胜感激。我一直试图理解它3天......

#include<bits/stdc++.h>
using namespace std;
const int MAXN = 5e3+5;
bool vis[MAXN];
int ar[MAXN];
int pre[MAXN];
vector<int> v;
int dp[MAXN];
void sieve() {
    v.push_back(2);
    for(int i=3;i<MAXN;i+=2) if(!vis[i]) {
        v.push_back(i);
        for(int j=i*i;j<MAXN;j+=2*i) vis[j]=true;
    }
}
int main() {
    // freopen("TASK.in","r",stdin);    
    // freopen("TASK.out","w",stdout);
    int n;
    cin>>n;
    assert(n<=5000);
    for(int i=1;i<=n;i++) {
        scanf("%d",&ar[i]);
        assert(ar[i]<=100000);
        pre[i]=pre[i-1]+ar[i];
    }
    sieve();
    dp[0]=dp[1]=0;
    for(int i=2;i<=n;i++) {
        dp[i]=dp[i-1];
        for(int j=0;j<(int)v.size() and v[j]<=i;j++) {
            int p=i-v[j]-1;//please explain this line
            if(p==-1) dp[i]=max(dp[i],pre[i]);
            else dp[i]=max(dp[i],dp[p]+pre[i]-pre[p+1]);// please explain this line 
        }
    }
    cout<<dp[n]<<endl;
    return 0;
}

1 个答案:

答案 0 :(得分:0)

此处array pre代表前缀sum,vector v包含MAXN以下的素数。您评论的第一行是 int p=i-v[j]-1;
此处v[j]是从jth开始的2素数,dp[i]是首次i问题的最佳分数。如果您解决v[j]个连续问题(来自i并向后),则从一开始就会出现i - v[j]个问题。 -1来自以下事实:您无法从(v[j] - 1) th(向后)解决i问题(如果您这样做,您将解决v[j] + 1个连续问题v[j]是素数。

你评论的第二行:
dp[i]=max(dp[i],dp[p]+pre[i]-pre[p+1]);
从上面开始,如果您从v[j](向后)解决i个问题,则会获得pre[i]-pre[p+1]分,并使用dp[p]添加,这是您已经获得的最佳结果{ {1}}。例如,如果pi = 10得到v[j] = 3,那就是您所期望的。