题目大意:
现在有n个人要买票,这n个人可以选择自己单独买票,也可以跟前面或者后面的人一起买票,现在告诉你每个人单独买票花费的时间以及相邻两个人买票花费的时间,问最少要花掉多少时间让每个人都卖完票。
题目分析:
用dp的思想去考虑这个问题,我们用dp[i]表示,到第i个人为止前面的人包括第i个人全买完票要花费的时间。
那么我们考虑状态转移方程,其实第i个人与后面的第i+1个人一起买票,第i+1个人与前面的i一起买票是等价的,因此我们每次只考虑第i个人跟前面的第i-1个人的关系就好了。
1.dp[i] = dp[i - 1] + time[i];也就是说如果第i个人单独买票,到他为止花费的时间就是前面第i-1个人买完的时间加上第i个人的买票时间。
2.dp[i] = dp[i - 2] + contime[i];也就是说如果第i个人跟他前面的i-1个人一起买票,应该是前面第i-2个人买完的时间加上他们两个一 起买的时间。
在这里做出几点说明:
1.到第i个人为止如果第i个人跟第i-1个人一起买票使得dp[i]取得了最小值,那么第i个人是不是就是不能跟第i+1个人一起买票了呢? 事实上如果我们考虑全局的话,有可能第i个人跟第i+1个人一起买票可能结果比第i个人跟前面的第i-1个人一起买票最终得到的结 果更优。
2.但是从我们的状态转移方程来看,我们兼顾了这两个方面,第一个状态转移方程,表示单独买。第二个状态转移方程表示的是第i个人跟他前面的第i-1个人一起买,但是这个时候加上的是dp[i - 2],由我们dp[i]的含义可以知道,这个时候第i个人没有与前面的第i-1个人一起买票,因此我们的顾虑也就是多余的了。
代码:
#include <bits/stdc++.h>
using namespace std;
const int INF = 0x3f3f3f3f;
const int maxn = 2000 + 5;
int a[maxn], b[maxn], dp[maxn];
int n;
int main()
{
int t = 0;
scanf("%d", &t);
while(t--)
{
scanf("%d", &n);
for(int i = 1; i <= n; i++)
scanf("%d", a + i);
for(int i = 2; i <= n; i++)
scanf("%d", b + i);
memset(dp, INF, sizeof(dp));
dp[1] = a[1];
dp[0] = 0;
for(int i = 2; i <= n; i++)
dp[i] = min(dp[i - 1] + a[i], dp[i - 2] + b[i]);
int time = dp[n];
int hh = time / 3600;
int mm = time / 60 - hh * 60;
int ss = time - hh * 3600 - mm * 60;
hh += 8;
if(hh < 12)
printf("%02d:%02d:%02d am\n", hh, mm, ss);
else
printf("%02d:%02d:%02d pm\n", hh - 12, mm, ss);
}
return 0;
}