教主泡嫦娥(RQNOJ 595)

題目描述

【問題背景】html

2012年12月21日下午3點14分35秒,全世界各國的總統以及領導人都已經匯聚在中國的方舟上。ios

但也有不少百姓平民想搭乘方舟,畢竟他們不想就這麼離開世界,因此他們決定要麼登上方舟,要麼毀掉方舟。app

 

LHX教主據說了這件事以後,果斷扔掉了手中的船票。在地球即將毀滅的那一霎那,教主自制了一個小型火箭,奔向了月球……spa

 

教主登上月球以後才發現,他的女友忘記帶到月球了,爲此他哭了一個月。code

但細心的教主立馬想起了小學學過的一篇課文,叫作《嫦娥奔月》,因而教主決定,讓嫦娥作本身的新任女朋友。htm

 

【題目描述】blog

教主拿出他最新研製的LHX(Let’s be Happy Xixi*^__^*)衛星定位系統,輕鬆地定位到了廣寒宮的位置。string

見到嫦娥以後,教主用溫柔而犀利的目光瞬間迷倒了嫦娥,但嫦娥也想考驗一下教主。it

嫦娥對教主說:「看到那邊的環形山了麼?你從上面那個環走一圈我就答應你~」io

 

教主用LHX衛星定位系統查看了環形山的地形,環形山上一共有N個能夠識別的落腳點,以順時針1~N編號。每一個落腳點都有一個海拔,相鄰的落腳點海拔不一樣(第1個和第N個相鄰)。

教主能夠選擇從任意一個落腳點開始,順時針或者逆時針走,每次走到一個相鄰的落腳點,而且最後回到這個落腳點。

教主在任意時刻,都會有「上升」、「降低」兩種狀態的其中一種。

 

當教主從第i個落腳點,走到第j個落腳點的時候(i和j相鄰)

j的海拔高於i的海拔:若是教主處於上升狀態,教主須要耗費兩段高度差的絕對值的體力;不然耗費高度差平方的體力。

j的海拔低於i的海拔:若是教主處於降低狀態,教主須要耗費兩段高度差的絕對值的體力;不然耗費高度差平方的體力。

 

固然,教主能夠在到達一個落腳點的時候,選擇切換本身的狀態(上升→降低,降低→上升),每次切換須要耗費M點的體力。在起點的時候,教主能夠自行選擇狀態而且不算切換狀態,也就是說剛開始教主能夠選擇任意狀態而且不耗費體力。

 

教主但願花費最少的體力,讓嫦娥成爲本身的女友。

 

【數據規模】

對於10%的數據,N ≤ 10;

對於30%的數據,N ≤ 100,a[i] ≤ 1000;

對於50%的數據,N ≤ 1000,a[i] ≤ 100000;

對於100%的數據,N ≤ 10000,a[i] ≤ 1000000,M ≤ 1000000000;

輸入格式

輸入的第一行爲兩個正整數N與M,即落腳點的個數與切換狀態所消耗的體力。

接下來一行包含空格隔開的N個正整數,表示了每一個落腳點的高度,題目保證了相鄰落腳點高度不相同。

輸出格式

輸出僅包含一個正整數,即教主走一圈所需消耗的最小體力值。

注意:C++選手建議使用cout輸出long long類型整數。

 樣例輸入:

6 7
4 2 6 2 5 6

樣例輸出:

27

【樣例說明】

從第3個落腳點開始如下降狀態向前走,並在第4個落腳點時切換爲上升狀態。

這樣共耗費4 +(7)+3+1+2^2+2^2+4=27點體力。

 

dp方程一臉很顯然的樣子:dp[i][0/1]表示走到i點,當前是上升/降低狀態的最小體力,可是因爲要枚舉起點,因此複雜度就不可承受了。
神奇的狀態設定是,用f[i][0/1][0/1]表示在第i個點,狀態爲上升或降低,是否改變過狀態, 轉移方程也不難,這裏就不說了。
最麻煩的是這種方案設定的及合理性,盜連接說明:http://blog.sina.com.cn/s/blog_9aa2786a0101700v.html

#include<iostream>
#include<cstdio>
#include<cstdlib>
#include<cstring>
#define N 10010
#define inf 10000000000000000LL
#define lon long long
using namespace std;
int a[N],n,m;
lon f[N][2][2];
lon sqr(lon x){return x*x;}
void dp(){
    f[0][0][1]=f[0][1][1]=inf;
    for(int i=1;i<=n;i++)
        for(int j=0;j<2;j++)
            if((a[i]<a[i-1])^j){
                f[i][j][0]=f[i-1][j][0]+abs(a[i]-a[i-1]);
                f[i][j][1]=min(f[i-1][j][1],
                           min(f[i-1][j^1][0],f[i-1][j^1][1])+m)+abs(a[i]-a[i-1]);
            }
            else {
                f[i][j][0]=f[i-1][j][0]+sqr(a[i]-a[i-1]);
                f[i][j][1]=min(f[i-1][j][1],
                           min(f[i-1][j^1][0],f[i-1][j^1][1])+m)+sqr(a[i]-a[i-1]);
            }
}
int main(){
    freopen("jh.in","r",stdin);
    scanf("%d%d",&n,&m);
    for(int i=0;i<n;i++) scanf("%d",&a[i]);
    a[n]=a[0];
    
    memset(f,0,sizeof(f));
    dp();
    lon ans=min(min(f[n][0][0],f[n][0][1]),min(f[n][1][0],f[n][1][1]));
    
    memset(f,0,sizeof(f));
    f[0][0][0]=inf;
    dp();
    ans=min(ans,f[n][1][1]-m);
    
    memset(f,0,sizeof(f));
    f[0][1][0]=inf;
    dp();
    ans=min(ans,f[n][0][1]-m);
    
    cout<<ans;
    return 0;
}
相關文章
相關標籤/搜索