• Educational Codeforces Round 83 (Rated for Div. 2) E


    挂机一个多小时都没想出来这道题,不过好在前四题切的快还是上分了

    看到有人说这题是区间DP裸题...我怀疑我要回炉再造了

    两种解法,一种是O(n^3)的区间DP

    先预处理哪些段可以合并成为一个数字,复杂度n^3,再区间DP

    f(i, j) = min(f(i, k) + f(k + 1, j)) ( i <= k < j)

    #include <cstdio>
    #include <algorithm>
    using namespace std;
    const int N = 510;
    int a[N], num[N][N], f[N][N];
    int main() {
        int n;
        scanf("%d", &n);
        for (int i = 1; i <= n; i++) {
            scanf("%d", &a[i]);
            num[i][i] = a[i];
        }
        for (int len = 1; len < n; len++)
            for (int l = 1; l <= n - len; l++) {
                int r = l + len;
                f[l][l] = 1;
                for (int i = l; i < r; i++)
                    if (num[l][i] == num[i + 1][r] && num[l][i] > 0)
                        num[l][r] = num[l][i] + 1;
                if (num[l][r] > 0)
                    f[l][r] = 1;
                else
                    f[l][r] = r - l + 1;
            }
        f[n][n] = 1;
        for (int len = 1; len < n; len++)
            for (int l = 1; l <= n - len; l++) {
                int r = l + len;
                for (int i = l; i < r; i++)
                    f[l][r] = min(f[l][r], f[l][i] + f[i + 1][r]);
            }
        printf("%d", f[1][n]);
        return 0;
    }

    但是其实有更美观复杂度更低的做法(学长教我的

    用栈把预处理优化到n^2,然后用d[i]表示前i个最少能变成几个,递推式就变成了

    d[i] = d[j - 1] + 1 (if i ~ j可以合并成一个)

    #include <cstdio>
    #include <algorithm>
    #include <stack>
    using namespace std;
    const int N = 510;
    int a[N], d[N];
    int main() {
    	int n;
    	scanf("%d", &n);
    	for (int i = 1; i <= n; i++)
    		scanf("%d", &a[i]);
    	for (int i = 1; i <= n; i++) {
    		stack < int > s;
    		d[i] = d[i - 1] + 1;
    		s.push(a[i]);
    		for (int j = i - 1; j > 0; j--) {
    			if (s.empty() || s.top() != a[j])
    				s.push(a[j]);
    			else {
    				int u = a[j];
    				while (!s.empty()) {
    					if (u != s.top())
    						break;
    					u = s.top() + 1;
    					s.pop();
    				}
    				if (s.empty())
    					d[i] = min(d[i], d[j - 1] + 1);
    				s.push(u);
    			}
    		}
    	}
    	printf("%d", d[n]);
    	return 0;
    }
    

      

  • 相关阅读:
    Redmine入门-安装
    【Spring Cloud笔记】 Eureka通过集群实现高可用
    【SpringBoot笔记】SpringBoot整合Druid数据连接池
    【Spring Cloud笔记】 断路器-hystrix
    【Spring Cloud笔记】Eureka注册中心增加权限认证
    Jenkins实现简单的CI功能
    【SpringBoot笔记】SpringBoot如何正确关闭应用
    Activi相关表归纳
    阿里云MySQL远程连接不上问题
    Storm入门-Storm与Spark对比
  • 原文地址:https://www.cnblogs.com/cminus/p/12461925.html
Copyright © 2020-2023  润新知