1. 程式人生 > 其它 >codeforces 1579G Codeforces Round #744 (Div. 3)

codeforces 1579G Codeforces Round #744 (Div. 3)

題意:

按順序給定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]
=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 */
View Code