题意
给n种颜色值,每种颜色值为r[i],数量为p[i],按颜色值递增顺序给出。
现在可以任意制造k个特殊值。
每种颜色值会找到和它差最小的特殊值,然后产生一个
(r[i]−k[i])2∗p[i]
(
r
[
i
]
−
k
[
i
]
)
2
∗
p
[
i
]
的权值。
问总权值最小是多少?
dp[i][j]表示,到第i个值,分成j段。每段都有一个特殊值。
那么转移方程就是
for (int i=1;i<=d;i++)
for (int j=1;j<=min(i,k);j++)
for (int l=j-1;l<i;l++)
dp[i][j] = min(dp[i][j], dp[l][j-1] + getval(l+1,i) );
有dp[l][j-1]代表前L个分成j-1段,然后(L+1,i)分成一段,计算总误差值。
其实在dp的中途不能保证每个颜色值是和离自己最近的特殊值算误差的。但是最后的结果一定保证了这个性质,因为如果不满足的话,肯定会有不同的分段,得到更小的误差值。
#include <bits/stdc++.h>
using namespace std;
const int MAXN = 300;
typedef long long ll;
ll r[MAXN],p[MAXN],suma[MAXN],sumb[MAXN],sumc[MAXN];
ll dp[MAXN][MAXN];
int n,k,d;
ll getval(int l,int r)
{
ll tmpa = suma[r] - suma[l-1];
ll tmpb = sumb[l-1] - sumb[r];
ll tmpc = sumc[r] - sumc[l-1];
double tmpx = -tmpb * 1.0 / (2*tmpa);
ll upx = ceil(tmpx), lowx = floor(tmpx);
ll ans1 = tmpa*upx*upx + tmpb*upx + tmpc;
ll ans2 = tmpa*lowx*lowx + tmpb*lowx + tmpc;
return min(ans1,ans2);
}
int main()
{
while ( scanf("%d%d",&d,&k) != EOF )
{
memset(dp,0x3f,sizeof dp);
dp[0][0] = 0;
for (int i=1;i<=d;i++) scanf("%I64d%I64d",&r[i],&p[i]);
for (int i=1;i<=d;i++)
{
suma[i] = suma[i-1] + p[i];
sumb[i] = sumb[i-1] + 2*r[i]*p[i];
sumc[i] = sumc[i-1] + r[i]*r[i]*p[i];
}
for (int i=1;i<=d;i++)
for (int j=1;j<=min(i,k);j++)
for (int l=j-1;l<i;l++)
dp[i][j] = min(dp[i][j], dp[l][j-1] + getval(l+1,i) );
printf("%I64dn",dp[d][k]);
}
return 0;
}
最后
以上就是拼搏自行车最近收集整理的关于2017-acmicpc-world-finals F - Posterize题意的全部内容,更多相关2017-acmicpc-world-finals内容请搜索靠谱客的其他文章。
发表评论 取消回复