1. 程式人生 > 其它 >DP專輯-codeforces1579-G. Minimal Coverage

DP專輯-codeforces1579-G. Minimal Coverage

這個題的轉移狀態不好想:

設f[i][j]為:在第i個數,當前位置與開頭位置距離為j時,end位置的最小值

我們不需要確定最左端位置在哪裡,只要知道相對位置就好了,可以想做將他們平移到零點

每次更新我們只要列舉和開始節點的長度 j 進行更新,注意到一點特徵,ai<=1000,那麼距離 j 肯定是 j<=2000的,可以想一下為什麼,詳細請看程式碼:

#include<bits/stdc++.h>
using namespace std;
int n,k;
int a[10005];
int dp[10005][2005];
void run()
{
    int n;
    cin>>n;
    
for(int i = 0; i<n+2; i++)for(int j =0; j<=2002; j++)dp[i][j]=99999999; for(int i=1; i<=n; i++) { cin>>a[i]; } dp[1][a[1]]=a[1]; for(int i=2; i<=n; i++) { for(int j = 0; j<=2000; j++) { if(a[i]+j<dp[i-1][j]) dp[i][a[i]
+j]=min(dp[i][a[i]+j],dp[i-1][j]); else { if(a[i]+j<=2000) dp[i][a[i]+j]=min(a[i]+j,dp[i][a[i]+j]); } if(a[i]<j) { dp[i][j-a[i]]=min(dp[i][j-a[i]],dp[i-1][j]); }
else { if(a[i]-j+dp[i-1][j]<=2000) dp[i][0]=min(dp[i][0],a[i]-j+dp[i-1][j]); } } } int ans =99999999; for(int i =0; i<=2000; i++) { ans=min(ans,dp[n][i]); } cout<<ans<<endl; } int main() { int t; cin>>t; while(t--) run(); return 0; }