ACM题解——动态规划专题——卖电影票

ACM题解——动态规划专题——卖电影票

题目描述

Jesus, what a great movie! Thousands of people are rushing to the cinema. However, this is really a tuff time for Joe who sells the film tickets. He is wandering when could he go back home as early as possible.
A good approach, reducing the total time of tickets selling, is let adjacent people buy tickets together. As the restriction of the Ticket Seller Machine, Joe can sell a single ticket or two adjacent tickets at a time.
Since you are the great JESUS, you know exactly how much time needed for every person to buy a single ticket or two tickets for him/her. Could you so kind to tell poor Joe at what time could he go back home as early as possible? If so, I guess Joe would full of appreciation for your help.

 

Input

There are N(1<=N<=10) different scenarios, each scenario consists of 3 lines:
1) An integer K(1<=K<=2000) representing the total number of people;
2) K integer numbers(0s<=Si<=25s) representing the time consumed to buy a ticket for each person;
3) (K-1) integer numbers(0s<=Di<=50s) representing the time needed for two adjacent people to buy two tickets together.

 

Output

For every scenario, please tell Joe at what time could he go back home as early as possible. Every day Joe started his work at 08:00:00 am. The format of time is HH:MM:SS am|pm.

 

Sample Input

2
2
20 
25
40
1
8

Sample Output

08:00:40 am
08:00:08 am

题意

有n个人买电影票各自需要的时长为ai,从头开始相邻两个人一起买票需要的时间为bi,求出最后所有人买完票所需的最短时间。这个时间要基于8:00am,求出结束时间。

题解

可以发现本题主要分为两部分,第一部分算出最短时间用秒来表示;第二部分将时间转化成结束的时间点。

先明确a[i]表示的是第i个人单独买票花费的时间,b[i]表示第i个人和第i+1个人一起买票共同花的时间,dp[i]记录到第i个人所花的最短时间。

得到dp的方式有两种,一种是在dp[i-1]的基础上加上a[i],另一种是在dp[i-2]的基础上i-1和i一起买票,即dp[i-2]+b[i-1],只需要在这两种方式中选取时间最短的即可;发现每一个dp在这两种方式上基于的dp[i-1]或者dp[i-2]都必须是当时的最短时间,对于i来说只需要判断当前这个i是要自己买票还是和前面一起买更省时间,所以也是一个贪心的过程,那么dp[0]=a[0],dp[1]=minn(dp[0]+a[1],b[0]);i从2开始循环到n-1即可(n为总人数,下标从0——n-1)。

所以状态方程为:dp[i]=min(dp[i-2]+b[i-1],dp[i-1]+a[i]) 。

 

则最后只需要求结束时间。分析数据最多的时长5*10^4,转化成小时为约为13.8h,约为14h,开始时间为8:00am,所以最后最晚不会超过第二天,所以只需要计算小时的数字会不会超过12,>=12时,标记输出pm,否则输出am;然后求出分、秒;小时、分、秒都需要注意的是最后求出来的结果小于10时前面要补一个0,以达成标准输出格式。最后注意‘:’只在三个数中间有。

代码

 

#include<iostream>
using namespace std;
int minn(int x,int y)
{
    if(x<y)
        return x;
    else
        return y;
}
int main()
{
    int t=0;
    cin>>t;
    for(int i=0;i<t;i++)
    {
        int n=0;
        cin>>n;
        int *a=new int[n+1];
        for(int j=1;j<=n;j++)
            cin>>a[j];
        int *b=new int[n];
        for(int j=1;j<n;j++)
            cin>>b[j];
        int *dp=new int[n+1];
        dp[0]=0;
        dp[1]=a[1];
        for(int j=2;j<=n;j++)
            dp[j]=minn(dp[j-2]+b[j-1],dp[j-1]+a[j]); //状态方程
        int h=dp[n]/3600;                            //计算时分秒
        int mi=(dp[n]%3600)/60;
        int sec=(dp[n]%3600)%60;
        bool flag=0;
        if(8+h<10)
        {
            flag=1;
            cout<<"0"<<8+h<<":";
        }
        else if(8+h<12)
        {
            flag=1;
            cout<<8+h<<":";
        }
        else
            cout<<8+h-12<<":";
        if(mi<10)
            cout<<"0"<<mi<<":";
        else
            cout<<mi<<":";
        if(sec<10)
            cout<<"0"<<sec<<" ";
        else
            cout<<sec<<" ";
        if(flag==0)
            cout<<"pm"<<endl;
        else
            cout<<"am"<<endl;
    }
    return 0;
}

 

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值