codeforces 1579G Codeforces Round #744 (Div. 3)
阿新 • • 發佈:2021-09-29
題意:
按順序給定n條線段,從0開始,可以正放也可以反放(+x,-x),問n條放完之後最小覆蓋區間長度。
思路:
很容易可以想到對於一個左端點找一個最左的右端點,但是如果是確定的左右座標,我們會無法知道當前的位置,然後無法進行轉移。
又考慮到左右端點和當前位置的具體座標其實不需要知道,我們只需要一個距離也就是相對長度。
所以不妨把左右端點以及當前位置進行相對位置的記錄。
那麼原本的dp[i][j]表示第i條的左端點的最優右端點變成了dp[i][j]表示第i條距離左端點的相對位置為j時右端點的最優解。
當j<a[i]時,說明此時-a[i]會移動左端點,那麼相對距離變成0,移左相當於移右。
其餘情況正常轉移。
而且值域必定在2000以內。
下附程式碼:
#include<bits/stdc++.h> using namespace std; const int INF=0X3f3f3f3f; int dp[10005][2005]; int main(){ int T; scanf("%d",&T); while (T--){ int n; scanf("%d",&n); for (int i=0; i<=n; i++){ for (int j=0; j<=2000; j++){ dp[i][j]View Code=INF; } } dp[0][0]=0; for (int i=1; i<=n; i++){ int x; scanf("%d",&x); for (int j=0; j<=2000; j++){ if (dp[i-1][j]!=INF){ if (j<x){ dp[i][0]=min(dp[i][0],dp[i-1][j]+(x-j)); }else { dp[i][j-x]=min(dp[i][j-x],dp[i-1][j]); } if (j+x<=2000) dp[i][j+x]=min(dp[i][j+x],max(dp[i-1][j],j+x)); } } } int res=INF; for (int i=0; i<=2000; i++){ res=min(res,dp[n][i]); } printf("%d\n",res); } } /*10 5 6 7 3 3 1 3 5 4 6 */