hdoj1421 搬寝室(基础DP)

题目:点击打开链接

一个简单的DP题目,我们可以这样思考,为了使疲劳度最低,我们则需要左右手拿的物品接近,则是a1<a2<a3<a4<a5<a6,这样的序列数,我们则是采取拿a1,a2和拿a3,a4,这样的结果则是疲劳度最低。

DP[i][j]表示拿i件物品需要搬j对.

状态转移方程则是dp[i][j]=min(DP(i-1,j),DP(i-2,j-1)+a[i-1]);

分析:第i件物品不搬,则是在前i-1件物品中搬j对

    第i件物品搬,则i-1件物品也要搬,那么则是在前i-2件物品中搬j-1对,再搬第i件

需要注意的是:

1.当2*j<i时,即要搬得数量超过了物品总量,这是不可能发生的,因此此时令dp[i][j]为无穷大.

2.当j==0时,即在一对物品都没搬时,疲劳值为0,此时dp[i][j]=0.

#include <stdio.h>
#include <string.h>
#include <math.h>
#include <iostream>
#include <stdlib.h>
#include <algorithm>
#include <map>
#include <queue>
using namespace std;

const int INF=0x7ffffff;
int dp[2001][2001];
int a[2010];

int DP(int i,int j)
{
	if(j*2>i)
		return INF;
	if(j==0)
		return 0;
	return dp[i][j];
}

int main()
{
	int n,k,i,j;
	while(cin>>n>>k)
	{
		for(i=1;i<=n;i++)
			cin>>a[i];
		sort(a+1,a+n+1);
		for(i=1;i<n;i++)
		{
			a[i]=a[i+1]-a[i];
			a[i]*=a[i];
		}
		for(j=1;j<=k;j++)
		{
			for(i=2;i<=n;i++)
			{
				dp[i][j]=min(DP(i-1,j),DP(i-2,j-1)+a[i-1]);
			}
		}
		cout<<dp[n][k]<<endl;
	}
	return 0;
}


你可能感兴趣的:(hdoj1421 搬寝室(基础DP))