首页 > 试题广场 >

买票问题

[编程题]买票问题
  • 热度指数:3717 时间限制:C/C++ 1秒,其他语言2秒 空间限制:C/C++ 256M,其他语言512M
  • 算法知识视频讲解

现在有n个人排队买票,已知是早上8点开始卖票,这n个人买票有两种方式:

第一种是每一个人都可以单独去买自己的票,第 i 个人花费 a[i] 秒。

第二种是每一个人都可以选择和自己后面的人一起买票,第 i 个人和第 i+1 个人一共花费 b[i] 秒。

最后一个人只能和前面的人一起买票或单独买票。

由于卖票的地方想早些关门,所以他想知道他最早几点可以关门,请输出一个时间格式形如:08:00:40 am/pm

时间的数字要保持 2 位,若是上午结束,是 am ,下午结束是 pm

进阶:时间复杂度,空间复杂度

输入描述:

第一行输入一个整数 T,接下来有 T 组测试数据。

对于每一组测试数据:输入一个数 n,代表有 n 个人买票。

接下来n个数,代表每一个人单独买票的时间 a[i]。

接下来 n-1 个数,代表每一个人和他前面那个人一起买票需要的时间 b[i]
1<= T <=100
1<= n <=2000
1<= a[i] <=50
1<= b[i] <=50



输出描述:
对于每组数据,输出一个时间,代表关门的时间 。
示例1

输入

2
2
20 25
40
1
8

输出

08:00:40 am
08:00:08 am
这个题最难的地方:中午12点是am
发表于 2021-04-18 03:19:01 回复(5)
直接用动态规划模拟买票的过程,但是要注意a中只有一个元素的情况,此时b会输入个空串,贼坑!
T = int(input())
while T:
    str_n = input()
    if not str_n:
        continue
    n = int(str_n)
    a = list(map(int, input().split()))
    if len(a) == 1:
        h = a[0] // 3600 + 8       # 小时
        m = a[0] % 3600 // 60      # 分钟
        s = a[0] % 60              # 秒
    else:
        b = list(map(int, input().split()))
        # f[i]为到第i个人为止,一共花费了多长时间
        f = [0]*n
        f[0] = a[0]
        f[1] = min(f[0] + a[1], b[0])
        for i in range(2, n):
            # 比较第i个人单独买票和与第i-1个人一起买票的时间,选择用时少的
            f[i] = min(f[i - 1] + a[i], f[i - 2] + b[i - 1])
        h = f[-1] // 3600 + 8       # 小时
        m = f[-1] % 3600 // 60      # 分钟
        s = f[-1] % 60              # 秒
    is_am = True
    if h > 12:
        h -= 12
        is_am = False
    am_or_pm = "am" if is_am else "pm"
    print("%02d:%02d:%02d %s" % (h, m, s, am_or_pm))
    T -= 1


发表于 2021-01-16 22:43:13 回复(11)
简单的dp
#include <bits/stdc++.h>
 
using namespace std;
 
int main() {
    int T;
    cin >> T;
    while (T--) {
        int n;
        cin >> n;
        vector<int> dp(n + 1, 0);
        vector<int> single(n);
        for (int i = 0; i < n; ++i) {
            cin >> single[i];
        }
        dp[1] = single[0];
        for (int i = 2; i <= n; ++i) {
            int twoSum;
            cin >> twoSum;
            dp[i] = min(dp[i - 1] + single[i - 1], dp[i - 2] + twoSum);
        }
         
        int seconds = dp[n];
        int hh, mm, ss;
        ss = seconds % 60;
        mm = (seconds / 60) % 60;
        hh = seconds / 3600;
        hh += 8;
        char s[3] = "am";
        if (hh > 12) {
            hh -= 12;
            s[0] = 'p';
        }
        printf("%02d:%02d:%02d %s\n", hh, mm, ss, s);
         
    }
     
     
    return 0;
}


发表于 2021-03-10 18:20:55 回复(0)
明显动态规划算法和打家劫舍问题有点像。
我们使用倒向遍历
T = int(input()) for x in range(T):
    n = int(input())
    a = list(map(int, input().split())) if len(a) == 1:
        h = a[0]//3600+8  m = a[0] % 3600//60  s = a[0] % 60  b = list(map(int, input().split()))
    b.append(a[-1])
    dp = [0]*(n+2)
    Time = 0  for i in range(n-1, -1, -1):
            dp[i] = min(dp[i+1]+a[i], dp[i+2]+b[i])
    h = dp[0] // 3600+8  m = dp[0] % 3600 // 60  s = dp[0] % 60  is_am = True  if h>12:
        h-= 12  is_am =False  am_or_pm = "am" if is_am else "pm"  print("%0.2d:%0.2d:%0.2d:%s"%(h,m,s,am_or_pm))

发表于 2022-02-20 17:43:09 回复(0)
发表于 2021-08-20 23:29:26 回复(0)

不需要额外的b空间及dp空间。相当于空间复杂度为O(1)
#include <iostream>
#include <cstdio>
#include <vector>
using namespace std;
int T = 0, n = 0;
int main() {
    cin >> T;
    while (T--) {
        cin >> n;
        vector<int> a(n, 0);
        for (int i=0;i<n;i++) cin >> a[i];
        int buf;
        int A = -1;
        int B = a[0];
        for (int i=1;i<n;i++) {
            cin >> buf;
            int temp = B;
            B = min(B+a[i], i==1?buf:A+buf);
            A = temp;
        }
        int all_time = B;
        int hh, mm, ss;
        ss = all_time % 60;
        mm = (all_time / 60) % 60;
        hh = all_time / 3600;
        hh += 8;
        if (hh > 12) {
            all_time -= 12;
            printf("%02d:%02d:%02d pm\n", hh, mm, ss);
        }
        else
            printf("%02d:%02d:%02d am\n", hh, mm, ss);
    }
    return 0;
}




发表于 2021-07-07 01:30:07 回复(0)
c++
#include<vector>
#include<iostream>
#include<iomanip>
#include<sstream>
#include<chrono>
using namespace std;
const int ONE_DAY = 60 * 60 * 24;
struct Time {
    int hours;
    int minutes;
    int seconds;
};
Time calTimeAfterSecond(int x) {
    Time start = { 8, 0, 0 };
    int totalSeconds = (x + 8 * 3600) % ONE_DAY;
    Time newTime;
    newTime.hours = totalSeconds / 3600;
    newTime.minutes = (totalSeconds % 3600) / 60;
    newTime.seconds = totalSeconds % 60;
    return newTime;
}
string formatTimeWithAMPM(Time time) {
    string ampm = "am";
    int hours = time.hours;
    if (hours >= 12) {
            hours -= 12;
    }

    if (hours == 0)
        hours = 12;
    stringstream ss;
    ss << setfill('0') << setw(2) << hours << ":" << setw(2) << time.minutes << ":"
       << setw(2) << time.seconds << " " << ampm;
    return ss.str();
}
int Netease2_8_4(int n, vector<int>& nums1, vector<int>& nums2) {
    if (n == 1)
        return nums1[0];
    vector<int> dp(n);
    dp[0] = nums1[0];
    dp[1] = nums1[0] + nums1[1] > nums2[0] ? nums2[0] : nums1[0] + nums1[1];
    for (int i = 2; i < n; i++) {
        dp[i] = min(dp[i - 1] + nums1[i], dp[i - 2] + nums2[i - 1]);
    }
    return dp[n - 1];
}
int main() {
    int T;
    cin >> T;
    while (T) {
        int a;
        cin >> a;
        vector<int> nums1;
        int a1 = a;
        while (a1) {
            int c;
            cin >> c;
            nums1.push_back(c);
            a1--;
        }

        int a2 = a - 1;
        vector<int> num2;
        while (a2) {
            int c;
            cin >> c;
            num2.push_back(c);
            a2--;
        }
        int seconds = Netease2_8_4(a, nums1, num2);
        Time time = calTimeAfterSecond(seconds);
        cout << formatTimeWithAMPM(time)<<endl;
        T--;
    }

}


发表于 2023-08-04 17:12:15 回复(0)
#include <iostream>
#include <vector>
using namespace std;
int cal(const vector<int>&a,const vector<int>&b,int n)
{
    //dp+状态压缩
    //dp[i]表示到i个人(i从1开始)需要花费的最小时间
    //第i个人在a中索引为i-1
    //dp[i]=min(dp[i-1]+a[i-1],dp[i-2]+b[i-2]);
    //由于只跟前一个和前前个状态相关,状态压缩
    int pree=0,pre=a[0];
    int cur=pre;//cur初始化为第一个值而不是0是因为只有一个人排队的情况
    for(int i=2;i<=n;++i){
       cur=min(pre+a[i-1],pree+b[i-2]);
       pree=pre;
       pre=cur;
    }
    return cur;
}
string getTime(int sec){
    int h=sec/3600;
    int m=(sec-3600*h)/60;
    int s=sec-h*3600-60*m;
    h+=8;
    char str[100]={0};
    if(h<=12) sprintf(str,"%02d:%02d:%02d am",h,m,s);
    else     sprintf(str,"%02d:%02d:%02d pm",h,m,s);
    return str;
}
int main()
{
    int T;
    cin>>T;
    while(T--){
        int n,temp;
        cin>>n;
        vector<int> a(n,0);
        vector<int> b(n-1,0);
        vector<int> dp(n+1,0);
        for(int i=0;i<n;++i){
            cin>>temp;
            a[i]=temp;
        }
        for(int i=0;i<n-1;++i){
            cin>>temp;
            b[i]=temp;
        }
        cout<<getTime(cal(a,b,n))<<endl;
    }
}


发表于 2022-04-21 11:25:35 回复(0)
看了评论才知道原来当只有一个人排队的时候竟然还会输出一个空串,但是样例里没有,改完直接ac。
发表于 2023-06-28 02:43:43 回复(0)
#python代码 (提交的测试用例n等于1的时候b会输入一个空串,但是题目示例:(20 25 40 8)
n等于1时b没有输入)
for _ in range(int(input())):
    n = int(input())
    a = list(map(int,input().split()))
    if n == 1:
        b = input()
        minTime = a[0]
    else:
        b = list(map(int,input().split()))
        c = [0]*n
        c[0] = a[0]
        c[1] = min(a[0]+a[1],b[0])
        for j in range(2,n):
            c[j] = min(c[j-1]+a[j],c[j-2]+b[j-1])
        minTime = c[-1]
    hour = (minTime//3600+8)%24
    minute = (minTime%3600)//60
    second = (minTime%3600)%60
    if 0 < hour <= 12:
        print(f"{hour:02d}:{minute:02d}:{second:02d}","am")
    else:
        print(f"{hour:02d}:{minute:02d}:{second:02d}","pm")
发表于 2023-03-31 16:17:17 回复(0)
import sys

input0 = []
i = 0
for line in sys.stdin:
    a = line.split('\n')[0]
    a = a.split(' ')
    tmp = []
    for j in a:
        if j:
            tmp.append(int(j))
    input0.append(tmp)
    i+=1
# print(input0)
def buyticket(n, arr1, arr2):
    n = n[0]
    dp = [float('inf') for i in range(n+1)]
    dp[0] = 0
#     print(arr1)
    for i in range(1,n+1):
#         if i>1:
#             print(i)
        dp[i] = min(dp[i-1]+arr1[i-1],dp[i-2]+arr2[i-2])
#         if i<2:
#             dp[i] = arr1[0]
    # print(dp)
    return dp[n]

i=1
while(i<len(input0)):
    n = input0[i]
    if input0[i][0] == 1:
        arr1 = input0[i+1]
        arr2 = [float('inf')]
        i += 2
    else:
        arr1 = input0[i+1]
        arr2 = input0[i+2]
        i += 3
#     print(n, arr1, arr2)
    time = buyticket(n, arr1, arr2)
    second = time % 60
    if second<10:
        second = '0'+str(second)
    hour = int(time/3600)
    minute = int((time - hour*60*60)/60)
    if minute<10:
        minute = '0'+str(minute)
    hour = hour+8
    if hour>12:
        hour = hour-12
        du = 'pm'
    else:
        du = 'am'
    if hour<10:
        hour = '0'+str(hour)

    print(f'{hour}:{minute}:{second}',f'{du}')
写算法十分钟,处理输入一小时。这种题的难点都集中在根本不知道题目输入了个啥玩意,想debug都不知道从何下手
发表于 2023-03-28 21:49:17 回复(0)
import sys

for line in sys.stdin:
    T = list(map(int,line.split()))[0]
    for _ in range(T):
        # n = list(map(int,input().split()))[0]
        n = int(input())
        a = list(map(int,input().split()))
        b = list(map(int,input().split()))
        # 如果只有一个人,b会输入一个空串
        if n>=2:
            dp = [0]*(n+1)
            dp[0] = 0
            dp[1] = a[0]
            for i in range(2,n+1):
                dp[i] = min(dp[i-2]+b[i-2],dp[i-1]+a[i-1])
            all = dp[n]
            h,m,s = all//3600+8, all%3600//60, all%60
            if all<=3600*5:
                print('{:02d}:{:02d}:{:02d} am'.format(h,m,s))
            else:
                print('{:0>2d}:{:0>2d}:{:0>2d} pm'.format(h,m,s))

        else:
            all = a[0]
            h,m,s = all//3600+8, all%3600//60, all%60
            if all<=3600*5:
                print('{:0>2d}:{:0>2d}:{:0>2d} am'.format(h,m,s))
            else:
                print('{:0>2d}:{:0>2d}:{:0>2d} pm'.format(h,m,s))

发表于 2023-02-26 16:13:58 回复(0)
中午12点到1点之间是am,我也是活久见
发表于 2022-03-26 17:40:46 回复(0)
#include<iostream>
#include<vector>
using namespace std;

int main() {
    int T;
    cin >> T;
    while (T--) {
        int length;
        cin >> length;
        int c1 = length;
        int c2 =length - 1;
        vector<int> sing;
        vector<int> doub;
        while (c1--) {
            int t;
            cin >> t;
            sing.emplace_back(t);
        }
        while (c2--) {
            int t;
            cin >> t;
            doub.emplace_back(t);
        }
        vector<int> dp(length);
        dp[0] = sing[0];
        for (int i = 1; i < length; i++) {
            dp[i] = min(dp[i - 1] + sing[i], dp[i - 2] + doub[i - 1]);
        }
        int hour = (8 + dp[length - 1] / 60 / 60) % 24;
        int minute = (0 + dp[length - 1] / 60) % 60;
        int second = (0 + dp[length - 1]) % 60;
        if (hour <= 12) {
            if (hour < 10) {
                cout << 0 << hour << ":" ;
            } else {
                cout << hour << ":" ;
            }
            if (minute < 10) {
                cout << 0 << minute << ":";
            } else {
                cout << minute << ":";
            }
            if (second < 10) {
                cout << 0 << second << " am" << endl;
            } else {
                cout << second << " am" << endl;
            }
        } else {
            cout << hour - 12 << ":" ;
            if (minute < 10) {
                cout << 0 << minute << ":";
            } else {
                cout << minute << ":";
            }
            if (second < 10) {
                cout << 0 << second << " pm" << endl;
            } else {
                cout <<second << " pm" << endl;
            }
        }
        
    }
    return 0;
}
发表于 2022-03-22 21:53:39 回复(0)
//原来是会出现两个人一起买反而时间用的多得情况啊
#include<iostream>
#include<math.h>
#include<iomanip>
using namespace std;
int main(){
    int t,n,cntt=0;
    cin>>t;//数据组数
    while(cntt<t){
        cin>>n;//人数
        int cntn=0;
        int a[2000],b[2000];
        for(int i=0;i<n;i++){ cin>>a[i];}
        for(int i=0;i<n-1;i++){ cin>>b[i];}
        int time=0;
        int dp[2000];
        if(n==1){
            time=a[0];
        }else{
            dp[0]=a[0];
            for(int i=1;i<n;i++){
                if(i-2<0){
                    dp[i]=min(a[0]+a[1], b[0]);
                }else{
               dp[i]=min(dp[i-2]+b[i-1],dp[i-1]+a[i]);
               }
            }
            time=dp[n-1];
        }
        int hour=time/3600;
        int minute=(time-hour*3600)/60;
        int second=time-hour*3600-minute*60;
        if(hour+8>12){
            cout<<setw(2)<<setfill('0')<<hour-12<<":"<<setw(2)<<setfill('0')<<minute<<":"<<setw(2)<<setfill('0')<<second<<" pm"<<endl;
        }else{
            cout<<setw(2)<<setfill('0')<<hour+8<<":"<<setw(2)<<setfill('0')<<minute<<":"<<setw(2)<<setfill('0')<<second<<" am"<<endl;
        }
        cntt++;
    }
}

发表于 2022-03-14 22:25:29 回复(0)
我是没想到12点算上午
发表于 2022-02-27 16:32:44 回复(0)
先dp求最短时间,然后模拟
#include <bits/stdc++.h>
#define INF 0x3f3f3f3f
//#define mod 998244353
#define mod 1000000007
#define ll long long
using namespace std;
const int N=2e3+5;
const double eps=1e-8;
int n,m,k,q;
int a[N],b[N],dp[N];
int solve(){
    cin>>n;
    for(int i=1;i<=n;i++)cin>>a[i];
    for(int i=2;i<=n;i++)cin>>b[i];
    if(n==1){
        return a[1];
    }
    dp[1]=a[1];
    for(int i=2;i<=n;i++){
        dp[i]=min(dp[i-1]+a[i],dp[i-2]+b[i]);
    }
    return dp[n];
}
void print(int h,int m,int s,int f){
    if(h==0)cout<<"00";
    else if(h<10)cout<<0<<h;
    else cout<<h;
    cout<<':';
    if(m==0)cout<<"00";
    else if(m<10)cout<<0<<m;
    else cout<<m;
    cout<<':';
    if(s==0)cout<<"00";
    else if(s<10)cout<<0<<s;
    else cout<<s;
    cout<<' ';
    if(f)cout<<"am"<<'\n';
    else cout<<"pm"<<'\n';
}
int main()
{
    ios_base::sync_with_stdio(false);
    cin.tie(0);cout.tie(0);
    cout<<fixed<<setprecision(10);
    int t;
    cin>>t;
    while(t--){
        int k=solve();
        k%=(60*60*24);
        int h=8,m,s;
        h+=k/3600;
        h%=24;
        k-=k/3600*3600;
        m=k/60;
        s=k%60;
        if(h<=12)print(h,m,s,1);
        else {
            h-=12;
            print(h,m,s,0);
        }
    }
    return 0;
}


发表于 2022-01-21 17:25:51 回复(0)
#include<iostream>
#include<vector>
#include<algorithm>
#include<string>
using namespace std;
string change(int tmp) {
    string str;
    if (tmp < 10) {//处理小于10的标准输出格式
        str = "0" + to_string(tmp);
    }
    else {
        str = "" + to_string(tmp);
    }
    return str;
}
void time(int t) {//组合成输出格式
    int hours = t / 3600 + 8;
    int minutes = (t - (hours-8) * 3600) / 60;
    int seconds = t % 60;
    string h = change(hours);
    string m = change(minutes);
    string c = change(seconds);
    cout << h << ":" << m << ":" << c << " "<<(hours<13?"am":"pm")<<endl;
}
int main() {
    int set = 0;
    cin >> set;
    while (set>0) {
        set--;
        int n;
        cin >> n;
        vector<int> a;
        vector<int> b;
        for (int i = 0; i < n; i++) {
            int tmp;
            cin >> tmp;
            a.push_back(tmp);
        }
        for (int i = 0; i < n - 1; i++) {
            int tp;
            cin >> tp;
            b.push_back(tp);
        }
        int* s=new int[n];//动态规划最优解数组
        s[0] = a[0];
        if (!b.empty()) {
            s[1] = min(s[0] + a[1], b[0]);
            for (int j = 2; j < n; j++) {
                s[j] = min(s[j-1] + a[j], s[j - 2] + b[j - 1]);
            }
        }
        time(s[n - 1]);
    }
}

发表于 2022-01-08 15:21:45 回复(0)
这个题要T干啥 呢?为啥需要一个T?
发表于 2021-09-18 05:16:12 回复(0)
讲道理,12:00:05就应该是pm啊?谁知道会在这里错
发表于 2021-08-21 18:08:26 回复(0)