題意:在一條長為
l l
的獨木橋上有很多石子 ,座標為 mi
' role="presentation" style="position: relative;">mim
i有乙隻青蛙要從座標零點跳到
l l
處或者跳過
l' role="presentation" style="position: relative;">l
l,每次青蛙可以跳過s∼
t s∼t
之間的任何正整數距離(包括s,
t s,t
),問青蛙最少要踩到過的石子數。(以上數字皆為正整數)
思路:咋一看就是乙個很簡單的一維dpdp
,狀態轉移方程:
dp[i
]=mi
n(dp
[i−j
]+fl
ag[i
]∣s<=
j<=t)dp
[i]=
min(
dp[i
−j]+
flag
[i]∣
s<=
j<=t)
說明:dp
[i]表
示到i點
踩的最少
石子數,
而要跳到
i點,只
有dp(
i−s)
∼dp(
i−t)
,從中取
最小值再
加上i點
有沒有石
子(fl
ag[i
])就行dp
[i]表
示到i點
踩的最少
石子數,
而要跳到
i點,只
有dp(
i−s)
∼dp(
i−t)
,從中取
最小值再
加上i點
有沒有石
子(fl
ag[i
])就行
但l l
的數值達到了 109
' role="presentation" style="position: relative;">10910
9,而石子的數目最多就只有
100 100
,中間很很多空白的地方造成了計算資源的浪費,於是按照狀壓的基本思想對長度進行壓縮。
公式已有大佬證過(這裡),得到壓縮路徑的方法:若兩個石子之間的距離
d>t∗
(t−1
)t∗(
t−1)
d>t∗
(t−1
)t∗(
t−1)
,則將他們的距離更改為 t∗
(t−1
)t∗(
t−1)t∗
(t−1
)t∗(
t−1)
。 因為
t<=
10 t
<=
10,因此我們可以直接將大於109109
的距離直接化為
90 90
. 而對於 s=
t s=t
需要特殊判斷。
**如下:
#include
#include
#include
#include
#include
using
namespace
std;
int l, s, t, m;
int m[105];
int dp[30000];
int f[105];
int flag[30000];
int main()
printf("%d\n", ans);
return
0; }
for(int i = 1; i <= m; i++)
scanf("%d",&m[i]);
sort(m + 1, m + 1 + m);//先排序
f[0] = 0;
m[0] = 0;
f[m + 1] = min(l - m[m], 100);//最後乙個點到終點的距離,雖然我認為不要100也行,但大點也沒啥關係
l = 0;
for(int i = 1; i <= m; i++)
l += f[m + 1];
for(int i = 1; i <= l + 9; i++)
}int minn = 0x3f3f3f3f;
for(int i = l; i <= l + 9; i++)
printf("%d\n",minn);//完
return
0;}
總結:動態規劃非常重要,至少要先熟悉各種dp。 洛谷P1052 過河 狀壓dp
在河上有一座獨木橋,乙隻青蛙想沿著獨木橋從河的一側跳到另一側。在橋上有一些石子,青蛙很討厭踩在這些石子上。由於橋的長度和青蛙一次跳過的距離都是正整數,我們可以把獨木橋上青蛙可能到達的點看成數軸上的一串整點 0,1,l 其中l是橋的長度 座標為0的點表示橋的起點,座標為l的點表示橋的終點。青蛙從橋的起...
洛谷P1052 過河(dp 狀壓)
題目鏈結 題目描述 在河上有一座獨木橋,乙隻青蛙想沿著獨木橋從河的一側跳到另一側。在橋上有一些石子,青蛙很討厭踩在這些石子上。由於橋的長度和青蛙一次跳過的距離都是正整數,我們可以把獨木橋上青蛙可能到達的點看成數軸上的一串整點 0,1,l 其中ll是橋的長度 座標為0的點表示橋的起點,座標為l的點表示...
洛谷P1052 過河 dp
題目大意 獨木橋長度l,橋上有m個石頭,要過橋,起點0,只要跳到或者跳過l都算過了,每次跳躍距離是s t之間的整數值,問跳過橋最少需要踩到的石子數 dp i 表示跳躍了距離i,最少需要踩到的石子數。stone i 表示在距離i有無石頭。狀態轉移方程 dp i min dp i dp i j ston...