#include <iostream>
#include <cstdio>
#include <cstring>
using namespace std;
const int maxx=100002;
int day[maxx];
__int64 dp[maxx][2];//dp[i][0]表示第i次出差去上海并回到北京的最小花费,dp[i][1]表示第i次出差去上海没有回到北京的最小花费
__int64 min(__int64 a,__int64 b){
return a<b?a:b;
}
int main(){
int t,a,b,cnt;
scanf("%d",&t);
for(int i=1;i<=t;i++){
scanf("%d%d%d",&cnt,&a,&b);
for(int j=0;j<cnt;j++){
scanf("%d",&day[j]);
}
dp[0][0]=(__int64)(2*a+b);//第一次去了回来则要花费来回的路费2*a再加上这一天损失的工资b
dp[0][1]=(__int64)(a+b);//第一次去了没有回来则只需要花费去的路费a和这一天损失的工资b
for(int j=1;j<cnt;j++){
dp[j][0]=min(dp[j-1][0]+2*a+b,dp[j-1][1]+(day[j]-day[j-1])*b+a);//这里的状态转移不用解释了 很显然
dp[j][1]=min(dp[j-1][0]+a+b,dp[j-1][1]+(day[j]-day[j-1])*b);
}
printf("Case #%d: ",i);
printf("%I64d\n",min(dp[cnt-1][0],dp[cnt-1][1]+a));//最后一次没回来的要加上让他回到北京 然后选择最小的就可以了
}
return 0;
}
hdu 4011 hdu 4011 hdu 4011 hdu 4011
优化了一下,本题因为状态转移方程是临近状态之间的转移,所以可以改为贪心。代码如下
#include <iostream>
#include <cstdio>
using namespace std;
int s[100002];
__int64 min(__int64 a,__int64 b){
return a<b?a:b;
}
int main(){
int ca;
scanf("%d",&ca);
for(int t=1;t<=ca;t++){
int n,a,b;
__int64 sum=0;
scanf("%d%d%d",&n,&a,&b);
for(int i=0;i<n;i++){
scanf("%d",&s[i]);
}
sum+=a*2+b;//刚开时必须去上海花费a工资b,最后一次必须回北京花费a
for(int i=1;i<n;i++){
__int64 x,y;
x=(s[i]-s[i-1])*b;//上次不用回去,只需加上延误的时间
y=2*a+b; //表示上次回去,所以先加上回去的费用a
sum+=min(x,y);//每次sum记录到上次来到上海的最小花费
}
printf("Case #%d: %I64d\n",t,sum);
}
return 0;
}