zoukankan      html  css  js  c++  java
  • 1644 免费馅饼 题解(c++)

    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;
    }



  • 相关阅读:
    hdu 2485 Destroying the bus stations 迭代加深搜索
    hdu 2487 Ugly Windows 模拟
    hdu 2492 Ping pong 线段树
    hdu 1059 Dividing 多重背包
    hdu 3315 My Brute 费用流,费用最小且代价最小
    第四天 下载网络图片显示
    第三天 单元测试和数据库操作
    第二天 布局文件
    第一天 安卓简介
    Android 获取存储空间
  • 原文地址:https://www.cnblogs.com/SBSOI/p/5575063.html
Copyright © 2011-2022 走看看