• 湖南师范大学2018年大学生程序设计竞赛新生赛补题


    模拟不想写,其他题目手残导致“爆零“”

    https://ac.nowcoder.com/acm/contest/127

    小小粉刷匠

    状态设计:假设将一个区间刷完最多需要x次(一个一个刷),当(a[i]==a[j])时,这样在决策当前区间的时候一次将整个区间刷成"(a[i])"后,这时次数相对于一个一个刷减少了一次

    若不相同,则就是两个区间合并成一个区间,即把它们都刷成目标状态的次数加起来

    由于这题限制了一次只能最多刷连续k个,所以当区间长度len>k时,一刷子不能从左刷到右,就不能通过(a[i]==a[j])进行转移,只能进行区间合并

    比大部分题解的代码都简介,状态也更优

    #pragma GCC optimize(2)
    #include<bits/stdc++.h>
    using namespace std;
    #define ll long long
    #define fastio ios::sync_with_stdio(false),cin.tie(NULL),cout.tie(NULL)
    const int maxn = 1e6 + 10;
    const int inf = 1e6;
    ll mod = 1e9 + 7;
    
    int dp[200][200];
    int main()
    {
        //freopen("C:\1.in", "r", stdin);
        fastio;
        int n, k;
        cin >> n >> k;
        vector<int>a(n + 1);
        memset(dp, 0x3f, sizeof(dp));
        for (int i = 1; i <= n; i++)
        {
            cin >> a[i];
            dp[i][i] = 1;
        }
        for (int len = 2; len <= n; len++)
        {
            for (int l = 1; l <= n - len + 1; l++)
            {
                int r = l + len - 1;
                if (len <= k && a[l] == a[r])
                    dp[l][r] = min(dp[l + 1][r], dp[l][r - 1]);
                else
                    for (int q = l; q < r; q++)
                        dp[l][r] = min(dp[l][r], dp[l][q] + dp[q + 1][r]);
            }    
        }
        cout << dp[1][n];
        return 0;
    
    }
    

    巨巨的提问

    状态设计:开dp数组dp[i][j][k],其中第一维为当前位置,第二维为当前多出的左括号个数(左-右必然得>=0),第三维为当前位置是否修改(连续修改不消耗次数,所以记录这个状态去转移连续修改)

    每新增一个括号时,都去记录修改它和不修改它两种状态所需的最小花费

    转移过程写在注释

    9/14/2020 update:开3维记录上一个位置的每个状态,很好的处理了只有(这个转移只有第一第三维)二维 没有的无后效性。

    #pragma GCC optimize(2)
    #include<bits/stdc++.h>
    using namespace std;
    #define ll long long
    #define fastio ios::sync_with_stdio(false),cin.tie(NULL),cout.tie(NULL)
    const int maxn = 1e6 + 10;
    const int inf = 1e6;
    ll mod = 1e9 + 7;
    
    int dp[2005][2005][2];
    int main()
    {
        fastio;
        int n;
        cin >> n;
        memset(dp, 0x3f, sizeof(dp));
        string s;
        cin >> s;
        s = '0' + s;
        dp[0][0][0] = 0;
        for (int i = 1; i <= n; i++)
        {
            for (int j = i; j >= 0; j--)//枚举多出的左括号数(从$dp[0][0][0]$开始转移的,因此不合法状态不会被转移,所以从i位全是括号开始枚举)
            {
                if (s[i] == '(')
                {
                    if (j)
                        dp[i][j][0] = min(dp[i - 1][j - 1][0], dp[i - 1][j - 1][1]);//假设不修改,则比上一个状态多了一个左括号
                    dp[i][j][1] = min(dp[i - 1][j + 1][0] + 1, dp[i - 1][j + 1][1]);//如果修改,则匹配一个左括号
                }
                else
                {
                    dp[i][j][0] = min(dp[i - 1][j + 1][0], dp[i - 1][j + 1][1]);//假设不修改,则匹配了上一个状态的一个左括号
                    if (!j)continue;
                    dp[i][j][1] = min(dp[i - 1][j - 1][0] + 1, dp[i - 1][j - 1][1]);//假设修改,则在上一个状态上加一个左括号
                }
            }
        }
        cout << min(dp[n][0][0], dp[n][0][1]);
        return 0;
    
    }
    
  • 相关阅读:
    一种循环方式
    SqlServer循环读取配置
    app抓包
    c# 前端写代码的情况
    第36月第27日 codesign重签名
    第36月第26天 吴恩达 目标检测
    第36月第25天 TensorFlow Object_detection
    第36月第19天 多个tomcat查端口
    第36月第8天 flask_bootstrap
    第36月第5天 升级到 XCode10.3 项目中的xib报错
  • 原文地址:https://www.cnblogs.com/ruanbaiQAQ/p/13526279.html
Copyright © 2020-2023  润新知