HDU 1421 搬寝室 类似背包DP
思路:把重物从小到大排序,计算出每2个相邻的重物产生的疲劳度,放在p[i]数组中,表示i与i+1这2个重物产生的疲劳度。
dp[i][j]表示进行到第i个物品(i前面的物品不一定都选了,跟背包差不多,i表示进行到第i个物品),已经选了j对物品 产生的最小疲劳度。
初始化:
先把所有值赋值为INF(无穷大),然后dp[i][0]=0;(0<=i<=n)因为没选重物之前疲劳度为0;
for(i=0;i<=n;i++) for(j=0;j<=k;j++) dp[i][j]=INF; for(i=0;i<=n;i++)dp[i][0]=0;
则状态转移方程为:
dp[i-1][j]表示没有选i这个物品, 当选了i这物品后就必须选i-1这个物品,选了这两个物品,那状态变为dp[i-2][j-1]+p[i-1];
dp[i][j]=min(dp[i-1][j],dp[i-2][j-1]+p[i-1])
AC代码

#include<stdio.h> #include<string.h> #include<algorithm> using namespace std; #define INF 100000000 int a[2001],p[2001]; int dp[2001][1001]; int main() { int i, j,n, k; while(~scanf("%d%d",&n,&k)) { for(i=1;i<=n;i++) scanf("%d",&a[i]); sort(a+1,a+n+1); for(i=1;i<n;i++) p[i]=(a[i+1]-a[i])*(a[i+1]-a[i]); for(i=0;i<=n;i++) for(j=0;j<=k;j++) dp[i][j]=INF; for(i=0;i<=n;i++)dp[i][0]=0; for(i=2;i<=n;i++) { for(j=1;j<=k;j++) dp[i][j]=min(dp[i-1][j],dp[i-2][j-1]+p[i-1]); } printf("%d\n",dp[n][k]); } return 0; }