CCF压缩编码和玲珑杯1066 - Buy Candy(平行四边形优化)

来源:互联网 发布:数据正态分布统计方法 编辑:程序博客网 时间:2024/06/09 05:42

玲珑杯1066 - Buy Candy(传送门)

题解

就是个简单的石子合并,一般的石子合并问题我们用O(n3)的复杂度解决,通过平行四边形优化可以达到降低一维,实现O(n2)的复杂度,平行四边形优化可以解决满足如下条件的问题:
dp[i][j] = min{dp[i][k]+dp[k+1][j]+w[i][j]}
我们用S[i][j]保存当前让dp[i][j]最优的k值,接着我们需要记住的就是,这个k值一定在S[i][j-1]到S[i+1][j]之间,不要问为什么,记住,如果有时间可以自己去了解里面的缘由
如此这道题目就可以用平行四边形优化了

代码

#include <cstdio>#include <cstring>#include <algorithm>using namespace std;typedef long long LL;const int MAXN = 1e3 + 5;const LL INF = (1LL << 60);int n, m;LL B[MAXN], A[MAXN];LL dp[MAXN][MAXN], S[MAXN][MAXN];LL sum[MAXN];LL f(LL x) {    LL ret = 0;    LL tmp = 1;    for(int i = 1; i <= m + 1; i ++) {        ret += A[i] * tmp;        tmp *= x;    }    return ret;}int main() {    int _;    scanf("%d", &_);    while(_ --) {        scanf("%d", &n);        for(int i = 1; i <= n; i ++) {            scanf("%lld", &B[i]);        }        scanf("%d", &m);        for(int i = 1; i <= m + 1; i ++) {            scanf("%lld", &A[i]);        }        sum[0] = 0;        for(int i = 1; i <= n; i ++) {            sum[i] = sum[i - 1] + B[i];        }        for(int i = 1; i <= n; i ++) {            dp[i][i] = 0;            S[i][i] = i;        }        for(int len = 1; len < n; len ++) {            for(int i = 1; i + len <= n; i ++) {                int end = i + len;                LL tmp = INF;                int mink = i;                //k在S[i][end-1]和S[i+1][end]之间                for(int k = S[i][end - 1]; k <= S[i + 1][end]; k ++) {                    if(dp[i][k] + dp[k + 1][end] + f(sum[end] - sum[i - 1]) < tmp) {                        tmp = dp[i][k] + dp[k + 1][end] + f(sum[end] - sum[i - 1]);                        mink = k;                    }                }                dp[i][end] = tmp;                S[i][end] = mink;            }        }        printf("%lld\n", dp[1][n]);    }    return 0;}

CCF压缩编码(传送门)

题解

首先要知道huffman编码是怎么来的,然后就是要保证有序,所以合并从huffman的合并最小的两个变成了合并相邻两个让其总和最小又是石子合并问题

代码和上面的没多大区别,可以说更加简单了

1 0
原创粉丝点击