luogu P1941 飛揚的小鳥

2022-02-27 18:32:19 字數 3213 閱讀 4710

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

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

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

小鳥每個單位時間沿橫座標方向右移的距離為1 ,豎直移動的距離由玩家控制。如果點選螢幕,小鳥就會上公升一定高度x ,每個單位時間可以點選多次,效果疊加;

如果不點選螢幕,小鳥就會下降一定高度y 。小鳥位於橫座標方向不同位置時,上公升的高度x 和下降的高度y 可能互不相同。

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

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

輸入格式:

輸入檔名為 bird.in 。

第1 行有3 個整數n ,m ,k ,分別表示遊戲介面的長度,高度和水管的數量,每兩個

整數之間用乙個空格隔開;

接下來的n 行,每行2 個用乙個空格隔開的整數x 和y ,依次表示在橫座標位置0 ~n- 1

上玩家點選螢幕後,小鳥在下一位置上公升的高度x ,以及在這個位置上玩家不點選螢幕時,

小鳥在下一位置下降的高度y 。

接下來k 行,每行3 個整數p ,l ,h ,每兩個整數之間用乙個空格隔開。每行表示一

個管道,其中p 表示管道的橫座標,l 表示此管道縫隙的下邊沿高度為l ,h 表示管道縫隙

上邊沿的高度(輸入資料保證p 各不相同,但不保證按照大小順序給出)。

輸出格式:

輸出檔名為bird.out 。

共兩行。

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

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

輸入樣例#1: 複製

10 10 6 

3 9

9 9

1 2

1 3

1 2

1 1

2 1

2 1

1 6

2 2

1 2 7

5 1 5

6 3 5

7 5 8

8 7 9

9 1 3

輸出樣例#1: 複製

1

6

輸入樣例#2: 複製

10 10 4 

1 2

3 1

2 2

1 8

1 8

3 2

2 1

2 1

2 2

1 2

1 0 2

6 7 9

9 1 4

3 8 10

輸出樣例#2: 複製

0

3

【輸入輸出樣例說明】

如下圖所示,藍色直線表示小鳥的飛行軌跡,紅色直線表示管道。

【資料範圍】

對於30% 的資料:5 ≤ n ≤ 10,5 ≤ m ≤ 10,k = 0 ,保證存在一組最優解使得同一單位時間最多點選螢幕3 次;

對於50% 的資料:5 ≤ n ≤ 2 0 ,5 ≤ m ≤ 10,保證存在一組最優解使得同一單位時間最多點選螢幕3 次;

對於70% 的資料:5 ≤ n ≤ 1000,5 ≤ m ≤ 1 0 0 ;

對於100%的資料:5 ≤ n ≤ 100 0 0 ,5 ≤ m ≤ 1 0 00,0 ≤ k < n ,0對於dp[i][j]表示第i列時,跳到第j個點的最小花費

這個n*m^2的dp方程很好想,上公升的情況列舉上乙個點的位置進行轉移,轉移o (n),考慮優化,dp[i][j]可以從第i列中上乙個轉移到的也就是dp[i-up[i-1]]]中選擇多跳一次轉移而成

複雜度o(1)

注意,轉移下降狀態要在轉移上公升狀態之後,否則上公升狀態不滿足單調上公升,即只進行上下操作其中的一種

#include#include

#include

using

namespace

std;

const

int maxn = 10007

;const

int maxm = 1007

;inline

intread()

intn,m,k;

intup[maxn],down[maxn];

inth[maxn],l[maxn],dp[maxn][maxm];

intin

[maxn];

intmain()

h[n]=m+1,l[n]=0

;

for(int p,i=1;i<=k;++i)

std::memset(dp,

0x3f,sizeof

dp);

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

;

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

if(j==m)

}//if(j+down[i-1]<=m)

//dp[i][j]=min(dp[i][j],dp[i-1][j+down[i-1]+1]);

}

for(int j=l[i]+1;j//

下降if(j+down[i-1]<=m)

dp[i][j]=min(dp[i][j],dp[i-1][j+down[i-1

]]);

}for(int j=1;j<=l[i];++j)dp[i][j]=0x3f3f3f3f

;

for(int j=h[i];j<=m;++j)dp[i][j]=0x3f3f3f3f

;

}int ans=0x3f3f3f3f

;

int cnt=k;

for(int i=n;i>=1;--i)

if(ans!=0x3f3f3f3f)break

;

if(in[i])cnt--;

}if(cnt!=k)

else

}

Luogu P1941飛揚的小鳥(DP)

我發現現在沒了題解我做普及提高 的題也做不了 更不要說這些提高 難度的 題 此題是乙個二維dp。暴力是三重迴圈ijk,k列舉在i位置上的點選次數。即 for int i 1 i n i for int j 1 j m j for int k 1 j k up i 0 k f i j min f i ...

題解 luogu P1941 飛揚的小鳥

首先想到設f i j 表示到第i行第j列所需要的最少點選螢幕次數。轉移方程為 f i j min 1 k j x 上公升 f i j min j y i 1 m 下降 顯然,下降可以o 1 轉移,主要問題在上公升的轉移。我們將上公升的方程變一下 f i j x i 1 min 這是 f i j x ...

P1941 飛揚的小鳥

定義dp i j 表示走到座標 i,j 時的最小點按次數。考慮遞推關係,能走到座標 i,j 一種情況是從前乙個位置下降上公升的轉移是乙個完全揹包,下降是01揹包。include using namespace std define ll long long define inf 0x3f3f3f d...