这段时间要沉迷刷题一段时间了,就让CSDN陪我一起吧!
一、题目大意
题目的大致意思是,我就不说背景直接抽象了。要建一条管道,管道由管子和支撑的柱子组成,给定n+1个点(0~n),以及单位长度管子的费用为a,柱子的费用为b。然后给定一个二进制串,长度为n,分别表示n个点的间隔,如果对应位置为1,则柱子高度要为2,否则柱子高度任意。好像不太好解释,详情参阅原题。
二、题目思路以及AC代码
突然感觉codeforce里,div2的题和div1+div2的题,难度好像不太一样,刚才差点做自闭了。
这题就是一个很典型的dp题,dp的思路也很明显。这里我们使dp[i][0]表示到第i个road 此时管道高度为1的最小经费,使dp[i][1]表示到第i个road 此时管道高度为2的最小经费,因为有些无定义的,由于题目要求求最小值,无定义的就直接置为无穷大即可。
这个dp有一个最基本的递推方程如下:
但这里要注意结合给定的二进制串,每次对以上递推公式选择使用。比如我的某个二进制串位置使1,那么说明这里只能高度为2,那么我就应该相应的把dp[i][0]设置为无穷,而不是按照递推公式求解。
下面给出AC代码:
#include <iostream>
#include <string>
#include <cstring>
#include <algorithm>
#define INF 0x3f3f3f3f3f3f3f3f
#define MAXN 200010
using namespace std;
typedef long long ll;
ll dp[MAXN][2]; // dp[i][0]表示到第i个road 此时管道高度为1的最小经费 INF为无定义
// dp[i][1]表示到第i个road 此时管道高度为2的最小经费
int n, a, b;
int main() {
int T;
cin >> T;
while (T--) {
cin >> n >> a >> b;
string s;
cin >> s;
dp[0][0] = b;
dp[0][1] = INF;
for (int i=1;i<n;i++) {
if (s[i] != '0' || s[i-1] != '0') {
dp[i][0] = INF;
dp[i][1] = min(dp[i-1][0]+2*a+2*b, dp[i-1][1]+a+2*b);
}
else {
dp[i][0] = min(dp[i-1][0]+a+b, dp[i-1][1]+2*a+b);
dp[i][1] = min(dp[i-1][0]+2*a+2*b, dp[i-1][1]+a+2*b);
}
}
cout << min(dp[n-1][0]+a+b, dp[n-1][1]+2*a+b) << endl;
}
return 0;
}
如果有问题,欢迎大家指正!!!