zoukankan      html  css  js  c++  java
  • @atcoder


    @description@

    给定 N 张排成一行的卡片,第 i 张卡片上面写着 Ai。

    重复以下操作,直到只剩下两张卡片。
    取出卡片 i,将卡片 i 左边的卡片与卡片 i 右边的卡片的 A 加上 Ai。

    求最后剩下的两张卡片的 A 的可能的最小和。

    Constraints
    2≤N≤18, 0≤Ai≤10^9(1≤i≤N)

    Input
    输入格式如下:
    N
    A1 A2 ... AN

    Output
    输出最小和。

    Sample Input 1
    4
    3 1 4 2
    Sample Output 1
    16

    先选 1 得到 4 5 2,再选此时的 5 得到 9 7,最小和 9 + 7 = 16。

    @solution@

    考虑最朴素的暴力:枚举排列,表示卡片被取走的顺序,然后算贡献。
    显然不够优秀。

    注意到对于按序排放的卡片 a b c,假如 b 不被取走,则 a, c 之间取的顺序并不重要。
    这意味着我们重复枚举了很多结果一样的状态。

    一个 Ai 贡献次数 = 左边第一个比它后取走的卡片贡献次数 + 右边第一个比它后取走的卡片贡献次数。我们总是认为第 1 张卡片与第 N 张卡片是最后取走的,且贡献次数为 1。

    考虑一种基于笛卡尔树的贡献计算方法:
    从根开始向下递归,同时维护该子树 左边第一个比它后取走的卡片贡献次数 与 右边第一个比它后取走的卡片贡献次数。那么就可以算出每个结点的贡献次数。

    那么我在搜索的时候可以一边枚举笛卡尔树的形态一边计算贡献。
    这样总搜索量 = 16 个点组成的二叉树数量 = 第 16 个卡特兰数 = 35357670。可以通过该题目。
    当然你可以用记忆化搜索。不过没有必要,而且 map 常数大,hash 反而麻烦了。

    @accepted code@

    #include <cstdio>
    #include <algorithm>
    using namespace std;
    typedef long long ll;
    const int MAXN = 20;
    const ll INF = (1LL<<60);
    int N; ll A[MAXN + 5];
    ll dfs(int l, int r, int cntl, int cntr) {
    	if( l + 1 == r ) return 0;
    	ll ret = dfs(l, l+1, cntl, cntl+cntr) + dfs(l+1, r, cntl+cntr, cntr) + (cntl+cntr)*A[l+1];
    	for(int i=l+2;i<=r-1;i++)
    		ret = min(ret, dfs(l, i, cntl, cntl+cntr) + dfs(i, r, cntl+cntr, cntr) + (cntl+cntr)*A[i]);
    	return ret;
    }
    int main() {
    	scanf("%d", &N);
    	for(int i=1;i<=N;i++)
    		scanf("%lld", &A[i]);
    	printf("%lld
    ", dfs(1, N, 1, 1) + A[1] + A[N]);
    }
    

    @details@

    我连暴搜都不会了.jpg。

    感觉用笛卡尔树理解起来更为直观,而且也更容易证明复杂度。

  • 相关阅读:
    安装redis报错 you need tcl 8.5 or newer in order to run redis test
    wm_concat函数oracle 11g返回clob
    ArrayList去重
    虚拟机linux下安装tomcat外部可访问
    虚拟机下Linux安装jdk
    本地硬盘和虚拟机之间复制文件
    VMware中为Linux安装vm-tools
    windows操作系统下载tomcat,并与eclipse进行整合
    Windows配置java运行环境的步骤
    Mac配置java运行环境的步骤
  • 原文地址:https://www.cnblogs.com/Tiw-Air-OAO/p/11794989.html
Copyright © 2011-2022 走看看