先上題:洛谷1052
題目描述
在河上有一座獨木橋,乙隻青蛙想沿著獨木橋從河的一側跳到另一側。在橋上有一些石子,青蛙很討厭踩在這些石子上。由於橋的長度和青蛙一次跳過的距離都是正整數,我們可以把獨木橋上青蛙可能到達的點看成數軸上的一串整點:0,1,……,l(其中l是橋的長度)。座標為0的點表示橋的起點,座標為l的點表示橋的終點。青蛙從橋的起點開始,不停的向終點方向跳躍。一次跳躍的距離是s到t之間的任意正整數(包括s,t)。當青蛙跳到或跳過座標為l的點時,就算青蛙已經跳出了獨木橋。
題目給出獨木橋的長度l,青蛙跳躍的距離範圍s,t,橋上石子的位置。你的任務是確定青蛙要想過河,最少需要踩到的石子數。
輸入
輸入檔案river.in的第一行有乙個正整數l(1 <= l <= 10^9),表示獨木橋的長度。第二行有三個正整數s,t,m,分別表示青蛙一次跳躍的最小距離,最大距離,及橋上石子的個數,其中1 <= s <= t <= 10,1 <= m <= 100。第三行有m個不同的正整數分別表示這m個石子在數軸上的位置(資料保證橋的起點和終點處沒有石子)。所有相鄰的整數之間用乙個空格隔開。
輸出
輸出檔案river.out只包括乙個整數,表示青蛙過河最少需要踩到的石子數。
如果本題資料範圍沒有這麼大,那麼將是一道非常簡單的dp。狀態轉移方程非常簡單:
設f[i]表示到達i點時所能踩得最少石子。
如果i點有石子:f[i]=min(f[i],f[i-j]+1)
如果i點沒有石子:f[i]=min(f[i],f[i-j])
但是看到這個題目的資料橋的長度<= 10^9,而石子的數量卻<= 100。所以這道題如果不加以離散化絕對會超時或者爆空間。那麼到底如何離散化呢?
我們其實可以將石子i與i-1之間的距離d[i]壓縮:
一。若距離在一跳之內就能跳完(或者一跳就會跳過),那麼距離無需壓縮:壓縮距離a[i]=a[i-1]+d[i]
二。若距離至少要兩跳及以上才能跳完,那麼距離就壓縮成兩跳。壓縮距離a[i]=a[i-1]+t+(d[i]%t);
壓縮完畢,接下來就是套用上面的狀態轉移方程,不過還有幾點要注意:
一。l也要壓縮,l=a[m]+((l-a[m])%t)+t。
二。青蛙最後一跳不一定剛剛好跳到橋尾,所以列舉的範圍應該是1到l+t-1。
三。記得青蛙的跳躍範圍是s-t而不是1-t!
#include
using
namespace
std;
int len,s,t,m,a[101],f[10001],d[101],k[101],minn=10001;
bool b[1001];
int main()
for(int i=1;i<=m;i++)//離散化過程
len=a[m]+((len-a[m])%t)+t;
for(int i=1;i<=len+t-1;i++)//dp
for(int j=s;j<=t;j++)
if(i-j>=0 && i-jif(!b[i])f[i]=min(f[i],f[i-j]);
else f[i]=min(f[i],f[i-j]+1);
} for(int i=len;i<=len+t-1;i++)
minn=min(minn,f[i]);
printf("%d\n",minn);
}
謝謝觀賞~ NOIP2005 狀壓DP 過河
題目描述 題目背景 noip2005提高組試題2。在河上有一座獨木橋,乙隻青蛙想沿著獨木橋從河的一側跳到另一側。在橋上有一些石子,青蛙很討厭踩在這些石子上。由於橋的長度和青蛙一次跳過的距離都是正整數,我們可以把獨木橋上青蛙可能到達的點看成數軸上的一串整點 0,1,l 其中l是橋的長度 座標為 0 的...
狀壓dp SCOI 2005 互不侵犯
題意 在n n n nn n的棋盤裡面放k kk個國王,使他們互不攻擊,共有多少種擺放方案。國王能攻擊到它上下左右,以及左上左下右上右下八個方向上附近的各乙個格仔,共8 88個格仔。考慮如何狀壓,對於每一行,我們用乙個長度為n nn的二進位制串表示每一行的狀態,比如1010 1010 1010 表示...
SCOI2005 互不侵犯(狀壓DP)
題意 給定乙個n n的棋盤,放置k個國王,使他們互相攻擊不到對方,共有多少種方案。國王可以攻擊上下左右,左上左下,右上右下附近的一格,共8格。資料範圍 1 n 9,0 k n n.因為n的範圍很小,而且每一行對應的乙個方案可以用乙個二進位制數表示,所以容易想到用狀壓dp。又因題目有限制要用多少個國王...