HNOI2009 通往城堡之路

2022-05-10 23:45:16 字數 3622 閱讀 9040

聽說公主被關押在城堡裡,彭大俠下定決心:不管一路上有多少坎坷,不管城堡中的看守有多少厲害,不管救了公主之後公主會不會再被抓走,不管公主是否漂亮、是否會鍾情於自己,他將義無反顧地朝著城堡前進。

可是,通往城堡的路上出現了一些情況。抽象地說,假象地圖在二維平面的第一象限。在每個橫軸的x位置上有乙個高為hx的支撐點,如果彭大俠沒有跳到支撐點上,那麼他就會掉下去,犧牲在路途。

開始時彭大俠在起點(1,h1)處,而城堡的入口在(n,hn)處。彭大俠每次可以從支撐點(x,hx)跳到支撐點(x+1,hx+1)。但是彭大俠每次的跳躍能量只有d,也就是說,每次跳躍必須滿足條件|hx+1-hn|<=d。換句話說,如果兩個相鄰支撐點的縱向落差大於d,那麼彭大俠就無法跳躍了!幸運的是,彭大俠還有乙個殺手鐗。 在起點處,他可以花乙個金幣,把某個支撐點公升高1個單位,或者降低1個單位。但是,起點處和城堡入口處的支撐點高度不能改變,並且一旦離開起點彭大俠就無法使用該殺手鐗。

彭大俠被告知100個金幣可兌換一單位生命。於是他希望通過少花金幣來儲存更多單位的生命。

他終於找到了你這位熱心的高手,請你幫他規劃一下以便耗費盡量少的金幣來到達城堡。

輸入格式:

檔案第一行包含乙個整數m(m<=5),表示問題求解次數。接下來的2m行依次表示每次求解的輸入資料塊。每個輸入資料塊佔2行,其中第一行包含兩個整數n和d,分別表示從起點到城堡入口處必須經過的支撐點數和每次跳躍允許的最大縱向落差,n和d之間用空格隔開,輸入資料保證2<=n<=5000,0<=d<=109;第二行包含用空格隔開的n個非負整數h1、h2、...、hn,其中hi(1<=i<=n)表示第i個支撐點的高度,特別地,h1表示彭大俠出發時所在支撐點的高度,hn表示城堡入口所在支撐點的高度,輸入資料保證對所有1<=i<=n有0<=hi<=109。

輸出格式:

有m行,第i(1<=i<=m)行表示第i次求解時彭大俠到達城堡必須耗費的最少金幣數量。若無論怎樣使用殺手鐗他都無法到達城堡,則輸出impossible。輸入資料保證答案在int64範圍之內。

輸入樣例#1:複製

3

10 2

4 5 10 6 6 9 4 7 9 8

3 16 4 0

4 23 0 6 3

輸出樣例#1:複製

6

impossible

4

對樣例中的第乙個輸入資料塊,d=2,把第三個支撐點降低3個單位,把第六個支撐點降低1個單位,把第七個支撐點公升高2個單位,原序列變成:4 5 7 6 6 8 6 7 9 8,這時任意相鄰支撐點的縱向落差沒有超過2,彭大俠可以到達城堡!

對樣例中的第二個輸入資料塊,d=1,這時不管怎樣調節第二個支撐點的高度,都無法使任意相鄰支撐點的縱向落差不超過1。

對樣例中的第三個輸入資料塊,d=2,這時,把第二個支撐點公升高1個單位,把第三個支撐點降低3個單位就滿足條件了。

【資料規模】

20%     n<=100

40% n<=1000

100% n<=5000

沒有看懂就去上面的**

首先,把b[i]=a[1]-(i-1)*d

也就是變成乙個向下的階梯

可以證明,最後i高度肯定是高於b[i]

同時我們需要把可行解的最後一項調整為原來的數才行。

每次調整,我們都只從乙個數開始到最後乙個數都向上調同樣的高度,因為這樣可以保證我調整後使費用減小的前提下序列依然符合要求,即相鄰兩個數的差小於等於d。

如果當前解大於a[i]那麼上公升高度會增大答案,所以要盡可能少上公升

同樣小於a[i]上公升高度減小答案,盡可能逼近

於是定義s=(b[i]a[i]的數量)

s越大,因為我們調整時是將這一段序列都往上調,所以乙個數比原解小,則對於它的調整會使改變量減少,即費用降低;否則,會使改變量增大,即費用公升高。

而且要使b[i]與a[i]盡可能近

上公升量dlt=min(a[i]-b[i])[a[i]>b[i]]

因為這樣我們 up 增加的值可以用 low 增加的值來==抵消==;

而且會有一部分 low 的值會使 ans 減小;

假設我們給j~n加上dlt,那麼要考慮b[j]+dlt<=b[j-1]+d的條件

dlt=min(dlt,b[j-1]+d-b[j])

直到a[n]=b[n]為止

假設通過上述操作,現在b[n]已經等於a[n],這個解法就是最優的

1.任何一段區間再增高,不會使答案更優

首先設該區間為[i,j],既然該區間能夠公升高,那麼則必有s1*h>s2*h--->s1>s2

假定[j+1,n]增加過,那麼在列舉字尾時,是不會遺漏的,所以此時[i,j]不增高是不可能的

假定[j+1,n]沒有增加過,那麼,b[j]與b[j+1]的差值必定為d,一旦增加b[j],則解必定不合法

2.任何一段區間再降低,不會使答案更優

設區間為[i,j]

假定[i,j]增高過,那麼降低就相當於增高的反操作,也就是撤銷增高---既然撤銷更優,那麼我們根本就不會增加它

假定[i,j]沒有增高過,那麼他們就必定不能降低---因為初始的b[i~j]已經是可行解的最低高度了

因為每一次起碼能把乙個b[i]提到與a[i]最近

所以o(n^2)

1 #include2 #include3 #include4 #include5

using

namespace

std;

6long

long ans,a[5005],b[5005],maxs,mind,dlt,n,d,inf=2e15,s;

7int

main()

8 20 b[1]=a[1

];21

for (i=2;i<=n;i++)

22 b[i]=b[i-1]-d;

23while (a[n]!=b[n])

2436

}37 dlt=min(dlt,b[j-1]+d-b[j]);

38for (i=j;i<=n;i++)

39 b[i]+=dlt;40}

41 ans=0;42

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

43 ans+=abs(a[i]-b[i]);

44 cout46 }

hnoi 2009 通往城堡之路

這道題並不是我想出來的。是看了網上乙個程式然後自己yy出這個程式是幹什麼的。這裡再放我的 其實和他的差不多,只是這樣方便看下文 然後大家看完了那篇文章之後如果沒懂 反正我當時是沒懂 這個程式首先對於原來的序列求出乙個解的下限,然後不斷的調整,直到得出可行解,首先,初始解是乙個不斷下降的序列,而且每次...

BZOJ1484 HNOI2009 通往城堡之路

作者部落格 正解 貪心 解題報告 做這道題做的我也是醉了 本來是找仙人掌題目的,搜尋bzoj仙人掌 bzoj1484!看了一下題目,excuse me?這跟仙人掌有啥關係?上網一搜題解,都說的很含糊,做法都是乙個不知道怎麼證明正確性的貪心 窩這麼弱就記住這個演算法好了 考慮我先做出所有點能取到的下界...

HNOI2009 夢幻布丁

題意 n個布丁擺成一行,進行m次操作.每次將某個顏色的布丁全部變成另一種顏色的,然後再詢問當前一共有多少段顏色.例如顏色分別為1,2,2,1的四個布丁一共有3段顏色.對每個顏色的位置維護鍊錶。合併兩個顏色,連線鍊錶,統計貢獻。統計貢獻的複雜度是與鍊錶長度有關的。如果遍歷長度短的鍊錶那麼複雜度自然更小...