POJ3666

POJ3666

此題對我意義非凡,畢竟看別人的博客能看暈倒是沒誰了。

同樣是初始化的問題。

然後,是個Dp.重點在於怎麼確定最優是從原數列中選取的。由於兩個或是遞增或是遞減,可以在中間或者兩個端點取得。三個的話,1,5,2,假設如此,最優同樣是2和5之間,包括端點,都可以取,然後5到此點的距離和2到此點的距離要加和,保持一定,所以點可以在這個區間裏取,然後若是1,5,-1,同樣所求的改變的最小爲5和-1 之間的距離爲6,而1在裏面,顯然取>=1這個點,若是其他點的話,就要多了1到這個點的距離,再想一下極限,就是5,4 再是無窮多個1,也是取1,也就是說取的點是和數據有關,所以,只能確定所有變化後的點都是由原數列的數得來的。至於爲什麼呢?再有一組數據7,6,5,4,3,2,7其中765可以確定中間點6可取,(5~7可取),432確定3可取(2~4可取)。那麼由於6>5>4>3,無論怎麼取,取4.~5則多了3*(5-4),3~4等也是。所以綜上所有組情況由上組合,都是可以轉化爲數列的一個數。

同時這個模型屬於常識,我看網上的博客有點暈,加上有的博客還誤導人。

#include<cstdio>

#include<iostream>

#include<cstring>

#include<algorithm>

using namespace std;

const int maxn=2003;

int a[maxn];

int b[maxn];

int dp[maxn][maxn];

int m=0;int n;int nm=1e9+2;

void solve()

{

    for(int i=1;i<=n;i++)

    {

        nm=dp[i-1][1];//

        for(int j=1;j<=n;j++)

        {

            nm=min(nm,dp[i-1][j]);

            dp[i][j]=nm+abs(a[i]-b[j]);

        }

    }

    int res=dp[n][1];

    for(int i=1;i<=n;i++)

    {

        //if(dp[n][i])

        res=min(res,dp[n][i]);

    }

    cout<<res<<endl;

}

int main()

{

    //int n ;

    cin>>n;

    for(int i=1;i<=n;i++)

    {

        cin>>a[i];

        b[i]=a[i];

    }

    sort(b+1,b+n+1);

    solve();

    return 0;

}

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章