• 「专题训练」Hard problem(Codeforces Round #367 Div. 2 C)


    题意与分析

    题意:给出(n)个字符串,可以反转任意串,反转每个串都有其对应的花费(c_i)。经过操作后是否能满足字符串(forall i in [1,n] ext{且} i in R_+, str[i]ge str[i-1]),若能输出最小花费,否则输出-1。
    分析:经过各种字符串dp血虐,应该会有个直觉:(dp[i])表示前(i)个串的最小花费。但是好像不太够:没有保存反转。因此,在dp中,如果状态不够,那就加维度保存状态。这里就是:我们定义(dp[i][0],dp[i][1])分别保存最后一个的反转状态即可。后面是很经典的套路了。

    代码

    #include <bits/stdc++.h>
    
    using namespace std;
    
    vector<string> vec, vecr;
    array<long long,100005> cost;
    array<array<long long,2>, 100005> dp;
    int main()
    {
    	ios::sync_with_stdio(false);
    	cin.tie(nullptr); cout.tie(nullptr);
    	int n; cin>>n;
    	for(int i=0;i!=n;++i)
    		cin>>cost[i];
    	for(int i=0;i!=n;++i)
    	{
    		dp[i][0]=dp[i][1]=1e15;
    		string tmp; cin>>tmp;
    		vec.emplace_back(tmp);
    		reverse(tmp.begin(), tmp.end());
    		vecr.emplace_back(tmp);
    	}
    	
    	dp[0][0]=0; dp[0][1]=cost[0];
    	int i;
    	for(i=1;i!=n;++i)
    	{
    		if(vec[i]>=vec[i-1])
    			dp[i][0]=dp[i-1][0];
    		if(vecr[i]>=vec[i-1])
    			dp[i][1]=dp[i-1][0]+cost[i];
    		if(vec[i]>=vecr[i-1])
    			dp[i][0]=min(dp[i][0], dp[i-1][1]);
    		if(vecr[i]>=vecr[i-1])
    			dp[i][1]=min(dp[i][1], dp[i-1][1]+cost[i]);
    		if(dp[i][0]==1e15 && dp[i][1]==1e15) break;
    	}
    	if(i==n) cout<<min(dp[n-1][0], dp[n-1][1])<<endl;
    	else cout<<-1<<endl;
    	return 0;
    }
    
  • 相关阅读:
    windows update error 0x8024401c
    linux杀毒软件ClamAV的安装使用
    firewalld防火墙设置
    RPM-GPG-KEY详解
    centos修改默认启动级别
    debian9.6修改系统语言
    ubuntu18.04修改网卡名称为eth0
    Windows server 1709(不含UI)模板部署
    NVIDIA-SMI系列命令总结
    bash: lspci: command not found解决方法
  • 原文地址:https://www.cnblogs.com/samhx/p/CFR367D2C.html
Copyright © 2020-2023  润新知