CF1207C Gas Pipeline(DP)

题目链接

题意:

你需要在城市里修建管道和支柱,管道和支柱的单位长度的价格分别为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;
}

 

posted @ 2020-02-11 22:48  晴天要下雨  阅读(261)  评论(0编辑  收藏  举报