原题连接:http://acm.hdu.edu.cn/showproblem.php?pid=1421
分析:用dp[i][j]保存最小疲劳值,i表示物品数,j表示搬的次数。
为使疲劳最小,要拿排序后相邻的两数。
动态转移方程为:
1、当拿K次数时物品都被拿完:dp[i][j]=dp[i-2][j-1]+(p[i]-p[i-1])*(p[i]-p[i-1]),
2、当拿K次数时物品未能拿完:dp[i][j]=min(dp[i-1][j],dp[i-2][j-1]+(p[i]-p[i-1])*(p[i]-p[i-1])); //看是否拿最后一个。
我的代码:
#include<stdio.h>
#include<string.h>
#include<algorithm>
using namespace std;
int dp[2010][2010];
int p[2010];
int main()
{
int n,k;
while(scanf("%d%d",&n,&k)!=EOF)
{
for(int i=1;i<=n;i++) scanf("%d",p+i);
sort(p+1,p+n+1);
for(int i=0;i<=n;i++)
for(int j=0;j<=k;j++) dp[i][j]=0;
for(int i=2;i<=n;i++)
{
for(int j=1;j<=k&&2*j<=i;j++)
{
if(j*2==i)
dp[i][j]=dp[i-2][j-1]+(p[i]-p[i-1])*(p[i]-p[i-1]);
else
dp[i][j]=min(dp[i-2][j-1]+(p[i]-p[i-1])*(p[i]-p[i-1]),dp[i-1][j]);
}
}
printf("%d\n",dp[n][k]);
}
return 0;
}
总结:以前做过的,今天做练习的时候又没有一次AC。