dp[i][0]=min( dp[i-1][0]+b[i], dp[i-1][1] )
dp[i][1]=dp[i-1][0]+a[i]
化简后得到 dp[i]=min( dp[i-1]+b[i], dp[i-2] + a[i-1] )
b[i] 代表单买需要的时间
a[i] 代表合买需要的时间
dp[i][0] 代表第 i 个人不与第 i+1 个人合买所需的最短时间
dp[i][1] 代表第 i 个人与第 i+1 个人合买所需的最短时间
0ms
#include<iostream>
#include<cstdio>
#include<cstring>
using namespace std;
#define min(a,b) ((a)<(b)?(a):(b))
const int maxn=2000+10;
int dp[maxn][2],a[maxn],b[maxn];
int main()
{
int n;
scanf("%d",&n);
while(n--)
{
memset(dp,0,sizeof(dp));
int k;
scanf("%d",&k);
for(int i=1;i<=k;i++)
scanf("%d",&b[i]);
for(int i=1;i<=k-1;i++)
scanf("%d",&a[i]);
dp[0][1]=b[1]; //初始化边界
for(int i=1;i<=k-1;i++)
{
dp[i][0]=min(dp[i-1][0]+b[i],dp[i-1][1]);
dp[i][1]=dp[i-1][0]+a[i]; //第i个人如果与后一个人合买 ,那么他一定不能与前一个人合买
}
int sum=min(dp[k-1][0]+b[k],dp[k-1][1]);
int h=8+sum/3600; //最晚不会超过24点,所以不需要模24
int m=sum%3600/60;
int s=sum%60;
printf("%02d:%02d:%02d ",h,m,s);
if(h>=12) printf("pm\n"); // 24 或 12 小时制都能过
else printf("am\n");
}
return 0;
}
以下为别人的代码
链接 Tickets
dp[i] 表示到第 i 个人买完票需要的最短时间
状态转移方程: dp[i]=min( dp[i-1]+a[i], dp[i-2]+b[i] )
a[i] 表示单买的时间,b[i] 表示 i 和 i-1 合买的时间。
15ms
#include<iostream>
#include<cstdio>
#include<cstring>
#include<cmath>
#include<algorithm>
#include<vector>
#include<set>
#define CLR(a,b) memset((a),(b),sizeof((a)))
using namespace std;
int const nMax = 3010;
int const inf=0x7fffffff;
int a[nMax],b[nMax];
int dp[nMax];
int n;
int DP()
{
CLR(dp,0);
dp[1]=a[1];
dp[2]=min(b[2],a[1]+a[2]);
for(int i=3;i<=n;i++){
dp[i]=min(dp[i-1]+a[i],dp[i-2]+b[i]);
}
return dp[n];
}
int main()
{
int t;
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]);
int t=DP();
t+=8*3600;
t%=(24*3600);
if(t/3600<12) printf("%02d:%02d:%02d am\n",t/3600,t%3600/60,t%3600%60);
else {
t-=12*3600;
printf("%02d:%02d:%02d pm\n",t/3600,t%3600/60,t%3600%60);
}
}
return 0;
}