题意:
你需要在城市里修建管道和支柱,管道和支柱的单位长度的价格分别为a,ba,b
给你一个长度为nn的0101序列,其中11表示这里需要通车,00表示这里不需要通车,高度为22的地方才可以通车(保证序列的头尾不需要通车)
如图,红色表示管道,黑色表示支柱,我们可以在一段单位区间建立一条S形线条,每个S形可以表示为该段由三部分组成:0.50.5个单位的水平管道+11个单位的垂直管道+0.50.5个单位的水平管道
每一段的单位区间左右都有支柱支撑,支柱的高度等于管道端点的高度
你需要保证所有通车的地方高度为22的同时,建管道和支柱的费用总和最小
思路:由于题目给定的限定条件,1.路长度为n,2.且每个点都有高度为1或者2,我们可以使用二维数组dp[i][j]来表示长度为i且当前高度为j时的最小花费。如果当前i是1,高度只能是2,如果当前i是0,那么如果i+1是1,他高度也为2,否则i+1是0,那么都可以。
状态转移方程:
dp[i][1]=min(dp[i-1][1]+b+a,dp[i-1][2]+b+2*a);
dp[i][2]=min(dp[i-1][1]+2*b+2*a,dp[i-1][2]+2*b+a);
#include<iostream> #include<cstdio> #include<algorithm> #include<cmath> #include<utility> #include<cstring> #include<string> #include<vector> #include<stack> #include<set> #include<map> #define inf 0x3f3f3f3f using namespace std; typedef long long ll; typedef pair<int,int> pll; const int maxn=2e5+10; const int mod =1e9+7; char s[maxn]; ll dp[maxn][3]; int main() { ios::sync_with_stdio(false); cin.tie(0); cout.tie(0); int t; cin >> t; while(t--) { memset(dp,0x3f,sizeof(dp)); int n,a,b; cin >>n >> a >> b; cin >> s+1; dp[0][1]=b; for(int i=1;i<=n;i++) { if(s[i]=='1'||s[i+1]=='1') { dp[i][2]=min(dp[i-1][1]+2*b+2*a,dp[i-1][2]+2*b+a); } else { dp[i][1]=min(dp[i-1][1]+b+a,dp[i-1][2]+b+2*a); dp[i][2]=min(dp[i-1][1]+2*b+2*a,dp[i-1][2]+2*b+a); } } cout << dp[n][1] << endl; /*cout << endl; for(int i=0;i<=n;i++) { for(int j=1;j<=2;j++) { cout << dp[i][j] << " "; } cout << endl; }*/ } return 0; }