題目描述:
題目背景:noip2005提高組試題2。
在河上有一座獨木橋,乙隻青蛙想沿著獨木橋從河的一側跳到另一側。在橋上有一些石子,青蛙很討厭踩在這些石子上。由於橋的長度和青蛙一次跳過的距離都是正整數,我們可以把獨木橋上青蛙可能到達的點看成數軸上的一串整點:0,1,……,l(其中l是橋的長度)。座標為 0 的點表示橋的起點,座標為 l 的點表示橋的終點。青蛙從橋的起點開始,不停的向終點方向跳躍。一次跳躍的距離是 s 到 t 之間的任意正整數(包括s,t)。當青蛙跳到或跳過座標為 l 的點時,就算青蛙已經跳出了獨木橋。
題目給出獨木橋的長度 l,青蛙跳躍的距離範圍 s,t ,橋上石子的位置。你的任務是確定青蛙要想過河,最少需要踩到的石子數。
輸入格式:
輸入檔案的第一行有乙個正整數 l(1 <= l <= 109
),表示獨木橋的長度。
第二行有三個正整數 s,t,m,分別表示青蛙一次跳躍的最小距離,最大距離,及橋上石子的個數,其中 1 <=s <= t <= 10,1 <= m <= 100。
第三行有 m 個不同的正整數分別表示這 m 個石子在數軸上的位置(資料保證橋的起點和終點處沒有石子)。
所有相鄰的整數之間用乙個空格隔開。
輸出格式:
輸出檔案只包括乙個整數,表示青蛙過河最少需要踩到的石子數。
樣例輸入:
10 2 3 5
2 3 5 6 7
樣例輸出:
2資料規模:
對於 30% 的資料,l <= 10000;
對於 100% 的資料,l <= 109
。 題目分析:
狀壓dp。本題橋很長,但是石子數少,考慮乙個性質:青蛙肯定能跳到距離它s∗
t 的位置,而對於大於s∗
t 的位置的每一點,就都可以跳到(因為青蛙可以跳的範圍是s~t,則它可以機智的調整自己跳的距離從而到底每一點)。既然這樣那麼就可以把相互距離大於s∗
t 的石子移成距離為s∗
t ,顯然是等效的,無額外影響,於是本題距離最大也就是s∗
t∗m<104
。然後就可以轉移了。f[i],下標為距離,存的是最少石子數。轉移方程: f[
i+j]
=min
(f[i
+j],
f[i]
+1) (此點有石子) f[
i+j]
=min
(f[i
+j],
f[i]
) (此點無石子)
特殊的,對於s=t,那麼只要石子位置是其倍數就會被踩。
附**:
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
using
namespace
std;
int l,s,t,m,sum,a[110],b[110],f[10010];
bool check[10010];
int main()
sort(a+1,a+m+1);
for(int i=1;i<=m;i++)
b[i]=a[i]-a[i-1];
for(int i=1;i<=m;i++)
memset(f,0x3f,sizeof(f));
f[0]=0;
for(int i=0;i<=a[m]+11;i++)
for(int j=s;j<=t;j++)
if(check[i+j]==true)
f[i+j]=min(f[i+j],f[i]+1);
else
f[i+j]=min(f[i+j],f[i]);
printf("%d\n",f[a[m]+11]);
return
0;}
NOIP 2005提高組 過河(狀壓DP) 詳解
描述 在河上有一座獨木橋,乙隻青蛙想沿著獨木橋從河的一側跳到另一側。在橋上有一些石子,青蛙很討厭踩在這些石子上。由於橋的長度和青蛙一次跳過的距離都是正整數,我們可以把獨木橋上青蛙可能到達的點看成數軸上的一串整點 0,1,l 其中l是橋的長度 座標為0的點表示橋的起點,座標為l的點表示橋的終點。青蛙從...
NOIP2005過河 DP 狀態壓縮
在河上有一座獨木橋,乙隻青蛙想沿著獨木橋從河的一側跳到另一側。在橋上有一些石子,青蛙很討厭踩在這些石子上。由於橋的長度和青蛙一次跳過的距離都是正整數,我們可以把獨木橋上青蛙可能到達的點看成數軸上的一串整點 0,1,l 其中l是橋的長度 座標為0的點表示橋的起點,座標為l的點表示橋的終點。青蛙從橋的起...
noip2005提高 過河 dp
由於l的範圍到了109,用普通dp做肯定是不成了 可以觀察到m的數量很小,dp在轉移的過程中有大量的無用轉移 可以想到壓縮範圍,問題是如何壓縮,觀察若s 9,t 10時,能到達的點,9,10,18,19,20,27,28,29,30,36,37,38,39,40.80,81,82,83,84,85,...