码迷,mamicode.com
首页 > 其他好文 > 详细

hdoj 1421 搬寝室 【dp】

时间:2014-09-10 17:56:00      阅读:175      评论:0      收藏:0      [点我收藏+]

标签:dp   好题   

题意。。。

首先从小到大排个序,并且分析之后可得, 如果要去第i个的话,则第i-1个物品也要取(因为是排过序的与i相差最小的就是i-1或者是i+1, 但是i+1与i也可以看做i和i-1, 所以如果要去第i个的话,则第i-1个物品也要取)。

分析:设dp[i][j]表示有i个物品,拿j对。则第i个物品对dp[i][j]有两种情况:

一:如果要不取第i个物品, 则此时的dp[i][j] = dp[i-1][j](仔细考虑一下)

二:如果要取第i个物品, 则此时有dp[i][j] = dp[i-2][j-1]+pow2(s[i]-s[i-1])(因为如果要去第i个的话,则第i-1个物品也要取,所以就是i-2,又因为又取了一对,所以是j-1);

注1:又因为是要找最小的疲劳值,所以取上面两种情况的最小值。

注2:初始化的时候dp[i][0] = 0,其他的都初始化为较大的数


代码:

#include <cstdio>
#include <cstring>
#include <algorithm>
#define M 2050
#define INF 0x7f7f7f7f
using namespace std;
int s[M];
int dp[M][M];

int pow2(int x){
	return x*x;
}

void solve(int n, int m){
	int i, j;
	for(i = 1; i <= n; i ++){
		for(j = 1; j <= n/2; j ++){
			dp[i][j] = INF;
		}
		dp[i][0] = 0;
	}
	for(i = 2; i <= n; i ++){
		for(j = 1; j <= i/2; j ++){
			dp[i][j] = min(dp[i-1][j], dp[i-2][j-1]+pow2(s[i]-s[i-1]));
		}
	}
	printf("%d\n", dp[n][m]);
}

int main(){
	int n, m, i;
	while(scanf("%d%d", &n, &m) == 2){
		for(i = 1; i <= n; i ++){
			scanf("%d", &s[i]);
		}
		sort(s+1, s+n+1);
		solve(n, m);
	}
	return 0;
}

题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=1421

hdoj 1421 搬寝室 【dp】

标签:dp   好题   

原文地址:http://blog.csdn.net/shengweisong/article/details/38864901

(0)
(0)
   
举报
评论 一句话评论(0
登录后才能评论!
© 2014 mamicode.com 版权所有  联系我们:gaon5@hotmail.com
迷上了代码!