【問題背景】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; }