程序師世界是廣大編程愛好者互助、分享、學習的平台,程序師世界有你更精彩!
首頁
編程語言
C語言|JAVA編程
Python編程
網頁編程
ASP編程|PHP編程
JSP編程
數據庫知識
MYSQL數據庫|SqlServer數據庫
Oracle數據庫|DB2數據庫
 程式師世界 >> 編程語言 >> C語言 >> C++ >> C++入門知識 >> 1644 免費餡餅 題解(c++)(S.B.S.),1644s.b.s.

1644 免費餡餅 題解(c++)(S.B.S.),1644s.b.s.

編輯:C++入門知識

1644 免費餡餅 題解(c++)(S.B.S.),1644s.b.s.


1644 免費餡餅(巴蜀oj上的編號)

  題面:

       

         SERKOI最新推出了一種叫做“免費餡餅”的游戲。         游戲在一個舞台上進行。舞台的寬度為W格,天幕的高度為H格,游戲者占一格。開始時,游戲者站在舞台的正中央,手裡拿著一個托盤。          游戲開始後,從舞台天幕頂端的格子中不斷出現餡餅並垂直下落。游戲者左右移動去接餡餅。游戲者每秒可以向左或右移動一格或兩格,也可以站在願地不動。          餡餅有很多種,游戲者事先根據自己的口味,對各種餡餅依次打了分。同時在8-308電腦的遙控下,各種餡餅下落的速度也是不一樣的,下落速度以格/秒為單位。當餡餅在某          一秒末恰好到達游戲者所在的格子中,游戲者就收集到了這塊餡餅。          寫一個程序,幫助我們的游戲者收集餡餅,使得收集的餡餅的分數之和最大。  輸入數據:         第一行:寬度W(1~99奇數)和高度H(1 ~ 100整數)        接下來給出了一塊餡餅信息。由4個正整數組成,分別表示了餡餅的初始下落時刻、水平位置、下落速度、分值。         游戲開始時刻為0。從1開始自左向右依次對水平方向的每格編號。  輸出數據:        收集到的餡餅最大分數之和。   ——————————————分割線————————————————————————————————————————————————————   題解:         由於餡餅下落的時間和速度都不同,人只能向左右移動,餡餅只能向下移動。人和餡餅都同時移動,思考起來比較復雜,因此我們需要轉變思路:        算出每個時刻落到最底層的每個格子有多少分值的餡餅。         如果將餡餅當成參照物,則餡餅向下落,可以看成餡餅不動,人往上走去摘取餡餅,這樣人每1時刻都可以走到上一行的5個格子,         這道題是經典動規模型數塔的變形,將餡餅落下的位置看做數塔中的列數,將下落的時間看做數塔中的行數,問題轉化為求解從塔底到塔頂的最長路徑。         計算出每個格子每個時刻可能達到的餡餅分值,填入W*H的天幕表。 代碼:
#include<iostream>
#include<cstdio>
#include<cstring>
#include<cmath>
#include<algorithm>
using namespace std;
int w,h;
struct pie
{
    int time,pos,speed,value,t;
}s[10001];//用結構體來記錄數據 
int f[1001][1001];//記錄決策 
int main()
{
    cin>>w>>h;
    int n=1,ss,maxn=-999,ans=0;
    //while (scanf("%d%d%d%d",s[n].time,s[n].pos,s[n].speed,s[n].value)==4) 
    while (cin>>s[n].time>>s[n].pos>>s[n].speed>>s[n].value)//由於不知道數據個數,用while讀入 
    {
    s[n].t=ceil(h/s[n].speed)+s[n].time;//t指該餡餅下落下來(到最後一格)的時間
        n++;//這一步核心意思就是將該時間取整,但是是加一位(2.....=3)
    }
    n-=1;//n為餡餅個數 
    for (int i=1;i<=n;i++)
    {
        f[s[i].pos][s[i].t]+=s[i].value;
        maxn=max(s[i].t,maxn);//找到最晚的餡餅的時間
    }
        for (int j=maxn-1;j>=0;j--)
         for (int i=1;i<=w;i++)
         { 
            if (f[i-2][j+1]&&i-2>0)    ans=max(ans,f[i-2][j+1]);
            if (f[i-1][j+1]&&i>1)      ans=max(ans,f[i-1][j+1]);
            if (f[i][j+1])             ans=max(ans,f[i][j+1]);
            if (f[i+2][j+1]&&i+2<=w)   ans=max(ans,f[i+2][j+1]);
            if (f[i+1][j+1]&&i+1<=w)   ans=max(ans,f[i+1][j+1]);
            f[i][j]+=ans;//狀態轉移方程應用 
         }
    cout<<f[w/2+1][0];//由於人以中間為起點,所以輸出(w/2+1,0)
    return 0;
}

 

  1. 上一頁:
  2. 下一頁:
Copyright © 程式師世界 All Rights Reserved