洛谷 P1941 飛揚的小鳥

題目連接

題目描述

Flappy Bird是一款風靡一時的休閒手機遊戲。玩家須要不斷控制點擊手機屏幕的頻率來調節小鳥的飛行高度,讓小鳥順利經過畫面右方的管道縫隙。若是小鳥一不當心撞到了水管或者掉在地上的話,便宣告失敗。html

爲了簡化問題,咱們對遊戲規則進行了簡化和改編:app

遊戲界面是一個長爲n,高爲m的二維平面,其中有k個管道(忽略管道的寬度)。 ide

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

小鳥每一個單位時間沿橫座標方向右移的距離爲1,豎直移動的距離由玩家控制。若是點擊屏幕,小鳥就會上升必定高度X,每一個單位時間能夠點擊屢次,效果疊加;若是不點擊屏幕,小鳥就會降低必定高度Y。小鳥位於橫座標方向不一樣位置時,上升的高度X和降低的高度Y可能互不相同。code

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

如今,請你判斷是否能夠完成遊戲。若是能夠,輸出最少點擊屏幕數;不然,輸出小鳥最多能夠經過多少個管道縫隙。blog

題目分析

這道題要求咱們求出到達最右端的最少可能點擊數,咱們不妨先只看兩步之間的關係——也就是從上一個橫座標位置到本橫座標位置的每個縱座標位置所須要的最小的點擊數。由此,對於每個縱座標位置,實際上其最小點擊數可能由上一步的某些縱座標位置轉移而來,而且全部的轉移出發位置與終止位置的關係均屬於一個方法集合。因而,咱們發現,這道題的實質是揹包問題。遊戲

把每一橫座標所對應縱座標的集合做爲揹包,將每一種轉移方法看成一個物品,其價值即爲點擊的總次數,而其費用即爲上升或降低的縱座標數,求在每一橫座標下花費每一費用所對應的最小价值,即可以將其看成揹包問題進行求解。在轉移以前判斷是否存在障礙物,以此做爲轉移是否可行的依據。注意小鳥轉移後原高度加上上升高度能夠高於m,但此時需將其高度特判爲m。get

代碼

 1 int main()
 2 {
 3     scanf("%d%d%d",&n,&m,&k);
 4     for(int i=1;i<=n;++i)
 5         scanf("%d%d",&x[i],&y[i]);
 6     memset(h,0x3f,sizeof h);
 7     for(int i=1;i<=k;++i)
 8     {
 9         scanf("%d",&p[i]);
10         scanf("%d%d",&l[p[i]],&h[p[i]]);
11     }
12     memset(f,0x3f,sizeof f);
13     for(int i=1;i<=m;++i)
14         f[0][i]=0;
15     for(int i=1;i<=n;++i)
16     {
17         for(int j=x[i]+1;j<=x[i]+m;++j)
18             f[i][j]=min(f[i-1][j-x[i]]+1,f[i][j-x[i]]+1);
19         for(int j=m+1;j<=m+x[i];++j)
20             f[i][m]=min(f[i][m],f[i][j]);
21         for(int j=1;j<=m-y[i];++j)
22             f[i][j]=min(f[i][j],f[i-1][j+y[i]]);
23         for(int j=1;j<=l[i];++j)
24             f[i][j]=0x3f3f3f3f;
25         for(int j=h[i];j<=m;++j)
26             f[i][j]=0x3f3f3f3f;
27     }
28     for(int i=1;i<=m;++i)
29         ans=min(ans,f[n][i]);
30     if(ans<0x3f3f3f3f)
31         printf("1\n%d",ans);
32     else
33     {
34         puts("0");
35         int place,j;
36         ans=0;
37         for(place=n;place>0;--place)
38         {
39             for(j=1;j<=m;++j)
40                 if(f[place][j]<0x3f3f3f3f)
41                     break;
42             if(j<=m)
43                 break;
44         }            
45         for(int i=1;i<=place;++i)
46             if(h[i]!=0x3f3f3f3f)
47                 ++ans;
48         printf("%d",ans);
49     }
50     return 0;
51 }
飛揚的小鳥
相關文章
相關標籤/搜索