题目链接:HDU - 1421 搬寝室

题意:

    n件物体里面,取2*k件(每次2件),每次疲劳度为两件物体质量差的平方,求结束后的最小疲劳度

    因为相邻的质量差最小,所以可以先排序,每次只用考虑从相邻的地方取

    对于每一个物体,分为取、不取两种可能(类似01背包)

    状态:dp[i][j]:表示从j个里面选2*i个时,最小的疲劳度

    转移方程:

        dp[i][j] = min(dp[i][j-1], dp[i-1][j-2] + (w[i]-w[i-1])*(w[i]-w[i-1]));

核心:

for(i = 1; i<=k; i++)
{
    for(j = i*2; j<=n; j++)
    {
        dp[i][j] = min (dp[i][j-1], dp[i-1][j-2] + (w[i]-w[i-1])*(w[i]-w[i-1]));
    }
}

代码:


#include <stdio.h>
#include <iostream>
#include <string.h>
#include <string>
#include <math.h>
#include <algorithm>
#include <queue>
#include <stack>
#include <map>
#include <vector>
#include <time.h>

using namespace std;

int w[2000+10];
int dp[1000+10][2000+10];

int main()
{
    //freopen("a.txt", "r", stdin);

	int n, k, i, j;
	while(~scanf("%d%d", &n, &k))
	{
		for(i = 1; i<=n; i++)
		{
			scanf("%d", &w[i]);
		}
		sort(w+1, w+n+1);
		memset(dp, 0, sizeof(dp));
		for(i = 1; i<=k; i++)
		{
			for(j = i*2; j<=n; j++)
			{
				if(j == i*2)
					dp[i][j] = dp[i-1][j-2]  + (w[j]-w[j-1])*(w[j]-w[j-1]);
				else 
					dp[i][j] = min(dp[i][j-1], dp[i-1][j-2] + (w[j]-w[j-1])*(w[j]-w[j-1]));
			}
		}
		printf("%d\n", dp[k][n]);
	}
    return 0;
}