[BZOJ]4953: [Wf2017]Posterize DP

Description

数字图像的像素可以用三个在0到255之间的整数表示,它们分别表示红色、绿色和蓝色的强度。为了压缩图片或是为了产生艺术效果,许多图像编辑工具收录了如下所述的”色调分离”操作。每个颜色通道会分别考虑,本题只考虑红色通道的情况。不同于在红色通道使用0到255之间全部的整数,一张色调分离后的图片只会使用这些数字里至多 k 种整数。每个像素原来的红色强度会被替换成最相近的可用强度。图像编辑工具会选择k个整数来最小化替换过程引起的平方误差之和。假设原图有n个像素,它们的红色取值是r1,···,rn,而 k 种可用整数为v1,···,vk ,那么平方误差之和被定义为
你的任务是计算可以实现的最小平方误差之和,参数k和图片的红色强度会给出。

题解:

区间DP。 f[i][j] 表示到第i种颜色,用了j种数字的最小代价,状态转移见代码。注意一下算 cost[i][j] (从i到j用一种数字的最小代价)时,若直接暴力,复杂度为 O(n2) ,会TLE,预处理几个前缀和,则可以 O(n) 求出。总时间复杂度为 O(n3)

代码:

#include<cstdio>
#include<cstring>
#include<iostream>
#include<algorithm>
using namespace std;
#define LL long long
const int maxn=270;
int d,k;
LL r[maxn],p[maxn],f[maxn][maxn],s1[maxn],s2[maxn],s3[maxn];
LL work(LL x,LL y)
{
    LL ans=(1LL<<62);
    for(LL i=0;i<256;i++)
    ans=min(ans,i*(s1[y]-s1[x-1])+i*i*(s3[y]-s3[x-1]));
    return ans+s2[y]-s2[x-1];
}
int main()
{
    memset(f,63,sizeof(f));
    scanf("%d%d",&d,&k);
    s1[0]=s2[0]=s3[0]=f[0][0]=0;
    for(int i=1;i<=d;i++)
    {
        scanf("%lld%lld",&r[i],&p[i]);f[0][i]=0;
        s1[i]=s1[i-1]-2*p[i]*r[i];
        s2[i]=s2[i-1]+p[i]*r[i]*r[i];
        s3[i]=s3[i-1]+p[i];
    }
    for(int i=1;i<=d;i++)
    f[i][1]=work(1,i);
    for(int i=1;i<=d;i++)
    for(int j=1;j<=i;j++)
    {
        LL cost=work(j,i);
        for(int l=2;l<=k;l++)
        f[i][l]=min(f[i][l],f[j-1][l-1]+cost);
    }
    LL ans=f[d][0];
    for(int i=1;i<=k;i++)ans=min(ans,f[d][i]);
    printf("%lld",ans);
}
  • 2
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值