题目链接:http://codeforces.com/gym/101471/attachments/download/5852/2017-acmicpc-world-finals-en.pdf
题目大意:
给你一个长度为n个不同的数,记为ri,每个数有pi个,然后你还有一个大小为k的集合,每个数记为vj,求:
题目思路:dp的思想
首先预处理出各区间关于某个k中元素的最小值。
然后进行dp推导。三重循环。
dp[i][j]=min(dp[i][j],dp[l][j-1]+f[l+1][i]);
dp[i][j]中i指的是前i个数,划分成j个部分的最小值,他可以有前l个数划分为j-1块加上(l+1,i)这一块,枚举求下最小值即可。
#include<bits/stdc++.h>
using namespace std;
const int maxn =380;
typedef long long ll;
ll dp[maxn][maxn];
ll f[maxn][maxn];
ll r[maxn],p[maxn];
int main()
{
int n,k;
scanf("%d%d",&n,&k);
for(int i=1;i<=n;i++)scanf("%I64d%I64d",&r[i],&p[i]);
memset(f,0x7f,sizeof f);
for(int l=0;l<256;l++)
{
for(int i=1;i<=n;i++)
{
ll ans=0;
for(int j=i;j<=n;j++)
{
ans+=(r[j]-l)*(r[j]-l)*p[j];
f[i][j]=min(f[i][j],ans);
}
}
}
memset(dp,0x7f,sizeof dp);
dp[0][0]=0;
for(int i=1;i<=n;i++)
{
for(int j=1;j<=k;j++)
{
for(int l=0;l<i;l++)
{
dp[i][j]=min(dp[i][j],dp[l][j-1]+f[l+1][i]);
}
}
}
printf("%I64d\n",dp[n][k]);
return 0;
}