题目链接
https://codeforces.com/problemset/problem/1207/C
题意:
排水工人正在铺管道,其中0表示非十字路口,1表示十字路口,十字路口时管道下面柱子的高度是平时高度的2倍。计算铺完全程所需要的管道和柱子最少多少钱。输入保证开始和最后都不是十字路口。
思路:
dp,利用dp[i][0]表示到第i个路口右边的柱子为普通柱子时所需要的最低花费,dp[i][1]第i个路口右边的柱子为高柱子所需要的最低花费,
如果当前路口是1,那么此时路口右边的柱子只能是高柱子
dp[i][1]=max(dp[i-1][1]+a+2*b)
如果当前路口是0,那么右边的柱子可能是普通柱子,也可能是高柱子
如果是普通柱子,
此时左边可能为普通柱子,也可能为高柱子,有:
dp[i][0]=min(dp[i][0],min(dp[i-1][0]+a+b,dp[i-1][1]+2*a+b));
如果是高柱子,
此时左边可能为普通柱子,也可能为高柱子,有:
dp[i][1]=min(dp[i][1],min(dp[i-1][0]+2*a+2*b,dp[i-1][1]+a+b*2));
由于输入数据保证最后不是十字路口,所以最右边一定是普通柱子,也就是dp[n][0]
#include<bits/stdc++.h>
using namespace std;
typedef long long ll;
char str[200010];
ll dp[200010][2];
ll inf=0x3f3f3f3f3f3f3f3f;
int main(){
int t;
scanf("%d",&t);
while(t--){
int n,a,b;
scanf("%d %d %d",&n,&a,&b);
getchar();//
scanf("%s",str+1);
for(int i=0;i<=n;i++) dp[i][0]=dp[i][1]=inf;
dp[0][1]=inf;
dp[0][0]=b;
for(int i=1;i<=n;i++){
if(str[i]=='1'){
dp[i][1]=min(dp[i][1],dp[i-1][1]+a+b*2);
}
else{
dp[i][0]=min(dp[i][0],min(dp[i-1][0]+a+b,dp[i-1][1]+2*a+b));
dp[i][1]=min(dp[i][1],min(dp[i-1][0]+2*a+2*b,dp[i-1][1]+a+b*2));
}
}
printf("%lld\n",dp[n][0]);
}
return 0;
}