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代码

View Code
#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;
}

 

 

posted @ 2012-08-08 21:16  To be an ACMan  Views(177)  Comments(0)    收藏  举报