NOIP2014 飛揚的小鳥

2022-05-21 18:12:11 字數 2830 閱讀 5371

為了簡化問題,我們對遊戲規則進行了簡化和改編:

遊戲介面是乙個長為 \(n\),高為 \(m\) 的二維平面,其中有 \(k\) 個管道(忽略管道的寬度)。

小鳥始終在遊戲介面內移動。小鳥從遊戲介面最左邊任意整數高度位置出發,到達遊戲介面最右邊時,遊戲完成。

小鳥每個單位時間沿橫座標方向右移的距離為 \(1\),豎直移動的距離由玩家控制。如果點選螢幕,小鳥就會上公升一定高度 \(x\),每個單位時間可以點選多次,效果疊加;如果不點選螢幕,小鳥就會下降一定高度 \(y\)。小鳥位於橫座標方向不同位置時,上公升的高度 \(x\) 和下降的高度 \(y\) 可能互不相同。

小鳥高度等於 \(0\) 或者小鳥碰到管道時,遊戲失敗。小鳥高度為 \(m\) 時,無法再上公升。

現在,請你判斷是否可以完成遊戲。如果可以,輸出最少點選螢幕數;否則,輸出小鳥最多可以通過多少個管道縫隙。

第 \(1\) 行有 \(3\) 個整數 \(n\), \(m\), \(k\), 分別表示遊戲介面的長度,高度和水管的數量,每兩個整數之間用乙個空格隔開;

接下來的 \(n\) 行,每行 \(2\) 個用乙個空格隔開的整數 \(x\) 和 \(y\),依次表示在橫座標位置 \(0 \sim n-1\) 上玩家點選螢幕後,小鳥在下一位置上公升的高度 \(x\),以及在這個位置上玩家不點選螢幕時,小鳥在下一位置下降的高度 \(y\)。

接下來 \(k\) 行,每行 \(3\) 個整數 \(p\), \(l\), \(h\),每兩個整數之間用乙個空格隔開。每行表示乙個管道,其中 \(p\) 表示管道的橫座標,\(l\) 表示此管道縫隙的下邊沿高度,\(h\) 表示管道縫隙上邊沿的高度(輸入資料保證 \(p\) 各不相同,但不保證按照大小順序給出)。

共兩行。

第一行,包含乙個整數,如果可以成功完成遊戲,則輸出 \(1\),否則輸出 \(0\)。

第二行,包含乙個整數,如果第一行為 \(1\),則輸出成功完成遊戲需要最少點選螢幕數,否則,輸出小鳥最多可以通過多少個管道縫隙。

我們來觀察一下題目,題目中有這樣一句話:

如果點選螢幕,小鳥就會上公升一定高度 \(x\),每個單位時間可以點選多次,效果疊加;如果不點選螢幕,小鳥就會下降一定高度 \(y\)。

根據這句話,我們可以發現我們在\(i\)位置的操作分為兩個部分,在位置\(i\)跳還是不跳,跳幾步。這樣對於跳還是不跳,我們可以看作是乙個\(01\)揹包,而跳幾次就可以看作是乙個完全揹包,為了避免衝突,我們先來考慮完全揹包的情況。

我們把高度看作是空間大小那麼,我們可以定義狀態為\(f[i][j]\)表示從起點到位置\((i, j)\)的最小步數。我們可以發現狀態\(f[i][j]\)是由上乙個狀態跳\(k\)下轉移過來的,而所謂的跳\(k\)下,我們可以用如下的狀態轉移方程來表示:$$f[i][j] = min(f[i - 1][j-x[i]], f[i][j - x[i])$$注意,我們觀察到,我們現在的轉移其實上是在\(i-1\)的位置跳了\(k\)下從而改變了\(i\)的高度,但是我們的呼叫的卻是\(x[i]\),這是我在做這道題時膜拜其他大佬時最不解的地方,但是,看了很多份都是這樣寫的,卻沒有說明原因,後來自己寫的時候才明白過來。在題目中有這樣的描述:

接下來的 \(n\) 行,每行 \(2\) 個用乙個空格隔開的整數 \(x\) 和 \(y\),依次表示在橫座標位置 \(0 \sim n-1\) 上玩家點選螢幕後,小鳥在下一位置上公升的高度 \(x\),以及在這個位置上玩家不點選螢幕時,小鳥在下一位置下降的高度 \(y\)。

但是,我們在儲存 \(x\) 和 \(y\) 的陣列時卻是這樣儲存的:

for(int i = 1; i <= n; ++ i)	scanf("%d%d", &x[i], &y[i]);
題目中描述的範圍是 \(0 \sim n - 1\), 而我們儲存的時候範圍是\(1 \sim n\)所以我們要後移一位這也是為什麼要呼叫而不呼叫\(x[i - 1]\)。

除此之外,這道題還有乙個亮(keng)點,如果鳥飛到天上了怎麼辦,為什麼它不去死,這個情況需要我們特判一下。

然後我們再來分析\(01\)揹包,我們可以先發現這個狀態轉移方程求更好寫了:$$f[i][j] = min(f[i][j], f[i - 1][j + y[i]])$$

在這之後我們需要去掉那些有水管擋住的情況,把他們都賦值為無窮大,表示無法到達。

統計答案時,我們只需要掃瞄一遍\(f[n][i]\)看是否能夠到,最小值即為有解情況的答案,如果沒有解,掃瞄\(0 \sim n-1\) 的所有位置,看是否有乙個\(x\)的所有高度都無法到達,即為答案。

#includeusing namespace std;

int low[10005], hight[10005], w[10005], x[10005], y[10005], f[10005][2005];

int main()

for(int i = 1; i<= m; ++ i) f[0][i] = 0;

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

int ans = f[0][0];

for(int i = 1; i <= m; ++ i) ans = min(ans, f[n][i]);

if(ans < f[0][0])

int overtime, flag, j;

for(overtime = n; overtime >= 1; -- overtime)

ans = 0;

for(int i = 1; i <= overtime; ++ i) ans += w[i];

printf("0\n%d\n", ans);

return 0;

}

NOIP2014 飛揚的小鳥

題目 分析 乙個揹包問題。i,j 是跳上來的情況時 可以由 i,j k 得到,則問題得到解決。注意 f陣列要先進行上公升操作,再進行下降操作,否則 i,j k 有可能是下降得到的,從而得到錯解 吸取我的教訓吧,調了好長時間 include include using namespace std co...

NOIP2014飛揚的小鳥

天哪細節問題調了乙個鐘,手速不夠快思路不夠清晰寫了乙個鐘,感覺一道第三題就要花掉我2個鐘那我比賽的時候腫麼辦qaq 說下這道題,首先純暴力,70分到手,然後我們把01揹包的轉移變成有上界的完全揹包,還有一些特殊情況特殊轉移,還是比較好看的,去年比賽不知是電腦問題還是什麼一直沒輸出,蠢到家了然後這題爆...

NOIP2014 飛揚的小鳥

傳送門 為了簡化問題,我們對遊戲規則進行了簡化和改編 1.遊戲介面是乙個長為n,高 為m的二維平面,其中有k個管道 忽略管道的寬度 2.小鳥始終在遊戲介面內移動。小鳥從遊戲介面最左邊任意整數高度位置出發,到達遊戲介面最右邊時,遊戲完成。3.小鳥每個單位時間沿橫座標方向右移的距離為1,豎直移動的距離由...