题意
现在有n个人要买电影票,如果知道每个人单独买票花费的时间,还有和前一个人一起买花费的时间,问最少花多长时间可以全部买完票。
解题
读题时有疑惑,一次性最多可以有几人一起买票?我对题意的一个理解是可以有k个人一起买票(1<=k<=N),以这个为基础写了一发WA。所以正确的题意理解是可以一次性买一个人的票或一次性买相邻的两个人的票。
因为要记录第i个买票是单独买还是和前面一个人一起买,所以设状态数组为dp[2][maxn]。dp[0][i]表示第i个人单独买时前i个人买票共需花费的最小时间。dp[1][i]表示第i个人与前一个人一起买时前i个人买共需花费的最小时间。
状态转移方程:
dp[0][i]=min{dp[0][i-1],dp[1][i-1]} + a[i];
dp[1][i]=min(dp[0][i-2],dp[1][i-2])+b[i];
a[i]表示第i个人单独买票所需时间。
b[i]表示第i个人与前一个人一起买票两人所需花费的总时间。
时间复杂度为O(N).
空间复杂度为O(2N).
#include <cstdio>
#include <algorithm>
#include <cstring>
#include <iostream>
using namespace std;
const int maxn=2e3+7;
int dp[2][maxn],a[maxn],b[maxn];
int main()
{
int T,K;
cin>>T;
while(T--)
{
cin>>K;
for(int i=1;i<=K;i++)
cin>>a[i];
for(int i=2;i<=K;i++)
cin>>b[i];
memset(dp,0,sizeof(dp));
dp[0][1]=a[1];
dp[1][1]=a[1];
for(int i=2;i<=K;i++)
{
dp[0][i]=min(dp[0][i-1],dp[1][i-1])+a[i];//单独买
dp[1][i]=min(dp[0][i-2],dp[1][i-2])+b[i];
}
int h,m,s,ans;
ans=min(dp[0][K],dp[1][K]);
ans+=8*60*60;
s=ans%60;
m=ans/60;
h=m/60;
m%=60;
printf("%02d:%02d:%02d %s\n",h>12?h-12:h,m,s,h>12?"pm":"am");
}
return 0;
}