NOIP 2005提高組 過河(狀壓DP) 詳解

2021-08-06 03:56:30 字數 2198 閱讀 4709

描述

在河上有一座獨木橋,乙隻青蛙想沿著獨木橋從河的一側跳到另一側。在橋上有一些石子,青蛙很討厭踩在這些石子上。由於橋的長度和青蛙一次跳過的距離都是正整數,我們可以把獨木橋上青蛙可能到達的點看成數軸上的一串整點:0,1,……,l(其中l是橋的長度)。座標為0的點表示橋的起點,座標為l的點表示橋的終點。青蛙從橋的起點開始,不停的向終點方向跳躍。一次跳躍的距離是s到t之間的任意正整數(包括s,t)。當青蛙跳到或跳過座標為l的點時,就算青蛙已經跳出了獨木橋。

題目給出獨木橋的長度l,青蛙跳躍的距離範圍s,t,橋上石子的位置。你的任務是確定青蛙要想過河,最少需要踩到的石子數。

對於30%的資料,l <= 10000;

對於全部的資料,l <= 10^9。

格式 輸入格式

輸入的第一行有乙個正整數l(1 <= l <= 10^9),表示獨木橋的長度。第二行有三個正整數s,t,m,分別表示青蛙一次跳躍的最小距離,最大距離,及橋上石子的個數,其中1 <= s <= t <= 10,1 <= m <= 100。第三行有m個不同的正整數分別表示這m個石子在數軸上的位置(資料保證橋的起點和終點處沒有石子)。所有相鄰的整數之間用乙個空格隔開。

輸出格式

輸出只包括乙個整數,表示青蛙過河最少需要踩到的石子數。

樣例1

樣例輸入1

10 2 3 5

2 3 5 6 7

樣例輸出1

這道題是狀態壓縮dp的經典例題,至於狀壓dp,就是將沒用的距離縮短,名字很高階,其實並不難,後面我們詳細解釋

本來這道題是一道十分普通的dp題,但大家可能都注意到l <= 10^9,對於如此大的資料,如果暴力dp,時間空間都會爆,所以就需要狀壓把沒用的長度壓縮掉

首先,我們不考慮長度的問題,看一下dp

這道題的dp思路並不難,就是迴圈列舉所有距離,每個距離再迴圈當前這步跳的距離s-t就行了。

a[i]表示位置i上有沒有石頭,有就是1,否則是0

f[i]表示跳到位置i的過程中踩到的最小石頭數

j表示當前這步跳的距離

狀態轉移方程:

f[i]=min(f[i],f[i-j]+a[i]);//十分簡單,f[i-j]+a[i]就是相當於這一步跳j踩到的石頭數
我們看到題目就會發現,l最大為10^9,而m最大只有100,可見石頭與石頭之間的距離是很大的,所以就要想辦法把每兩個石頭之間的距離縮短。

而壓縮石頭間距離的依據是:由於每次跳能跳s-t,所以從某一固定位置到某一位置p後,任意位置都可以被跳到。

我們用乙個圖來理解這句話(下圖中設s=2,t=4,線段為跳躍過程)

可見對於這種情況,p=3,也就是3以後的所有點都能跳到

對應到題目中,也就是說假如從某一石頭(就是剛剛提到的固定位置)開始跳,有可能在到達下一石頭前,就到達了p(也就是在到達下一石頭前,就能夠跳到所有點),這樣子的話,在p到下一石頭之間的所有距離都是沒有用的,可以被壓縮。

而經過考證,因為s,t都小於10,對於這個範圍最大p值為90,所以我們就把所有石頭兩兩間的距離縮短到90以下(不追求完美主義,90不一定是最優的,但肯定是沒錯的)

#include 

#include

#include

#include

using

namespace

std;

int l,s,t,m,rock[101],f[1100000],a[1100000];

//a[i]表示位置i上有沒有石頭,有就是1,否則是0

//f[i]表示跳到位置i的過程中踩到的最小石頭數

void specialjudge()

}cout

l=(l-rock[m])%90+rock[m];//把最後的l也往前移動

for (int i=1;i<=m;i++)

}void dp() //dp,實際上思想十分基礎 }}

int ans=0x7f;

for (int i=l;i<=l+t;i++)

sort(rock+1,rock+m+1);

if (s==t)

compress();

dp();

return

0;}

noip2005提高組過河

介於被這道題折磨了一晚上,因此很有必要記錄下來做動態規劃及狀態壓縮中易錯事項。題目大意 共m個石子,求青蛙每次以s到t步從座標0跳過座標l踩到的最小石子數。樣例資料 輸入10 2 3 5 2 3 5 6 7 輸出資料範圍 1 l 10 9 1 s t 10,1 m 100 初看此題,可以想到動態規劃...

NOIP2005提高組 過河

在河上有一座獨木橋,乙隻青蛙想沿著獨木橋從河的一側跳到另一側。在橋上有一些石子,青蛙很討厭踩在這些石子上。由於橋的長度和青蛙一次跳過的距離都是正整數,我們可以把獨木橋上青蛙可能到達的點看成數軸上的一串整點 0,1,l 其中l是橋的長度 座標為0的點表示橋的起點,座標為l的點表示橋的終點。青蛙從橋的起...

NOIP2005 狀壓DP 過河

題目描述 題目背景 noip2005提高組試題2。在河上有一座獨木橋,乙隻青蛙想沿著獨木橋從河的一側跳到另一側。在橋上有一些石子,青蛙很討厭踩在這些石子上。由於橋的長度和青蛙一次跳過的距離都是正整數,我們可以把獨木橋上青蛙可能到達的點看成數軸上的一串整點 0,1,l 其中l是橋的長度 座標為 0 的...