首页 > 代码库 > hdoj 1421 搬寝室 【dp】
hdoj 1421 搬寝室 【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】
声明:以上内容来自用户投稿及互联网公开渠道收集整理发布,本网站不拥有所有权,未作人工编辑处理,也不承担相关法律责任,若内容有误或涉及侵权可进行投诉: 投诉/举报 工作人员会在5个工作日内联系你,一经查实,本站将立刻删除涉嫌侵权内容。