hdu1421n中选k个不相邻数的最小值

来源:互联网 发布:考研作息知乎 编辑:程序博客网 时间:2024/04/29 01:09
//题目大意:有n个物品.每个物品有重量.一个人需要搬动k次物品.每次用两只手搬动.消耗疲劳值为左右手重量差的平方.//         求消耗疲劳的最小值//解题思路:自己做的时候把n个物品转换成n-1个物品.转换通过把n个物品排序.依次相减平方.那么所选的k个值//         必定是从这n-1个中选出来的..同时要求k个值没有任意两个是相邻的.//         dp转移方程为dp[i][j][0] 表示前i件物品中选择j件物品.第三维0,1分别表示是否选择最后一个.//         那么dp[i][j][0] = min(dp[i-1][j][0] , dp[i-1][j][1]);//             dp[i][j][1] = dp[i-1][j-1][0] + cas[i];//         同时由于第i次只与第i-1次有关.所以可以采用滚动数组的办法.//         后来看了网上的代码.这是一个经典的dp问题.dp[i][j] = min(dp[i-1][j] , dp[i-2][j-1] + cas[i]);//         对于dp经典问题.要融会贯通其dp转移方程.许多dp题目都是源自于一些经典的dp问题转移方程.//         转移方程翻译过来就是dp[i][j]的值源自于两种情形.前i-1个中选择j个的最优值.和前i-2个中选择j-1个的//         最优值.dp[i-1][j]就相当于默认不选择第j个dp[i-2][j-1]就相当于默认选择第i个.//         而不用像我自己的转移方程那样去分开来讨论..//题目连接:http://acm.hdu.edu.cn/showproblem.php?pid=1421 以下是自己转移方程写的和标准转移方程写的题目#include<stdio.h>#include<stdlib.h>#include<iostream>#include<math.h>#include<vector>#include<algorithm>#include<stack>#include<queue>#include<string.h>using namespace std;int n,k;int dp[4][2222][4],f[2002][1001];int a[2222],cas[2222];int main(){    while(scanf("%d%d",&n,&k) != EOF)    {        for(int i = 1 ; i <= n ; i++)scanf("%d",&a[i]);        sort(a+1,a+n+1);        for(int i = 1 ; i < n ; i++)          cas[i] = (a[i+1] - a[i]) * (a[i+1] - a[i]);        memset(f,0x3f3f3f3f,sizeof(f));//        for(int i = 0 ; i < n ; i++)f[i][0] = 0;//        f[1][1] = cas[1];//        for(int i = 2 ; i < n ; i++)//        for(int j = 1 ; j * 2 <= i + 1; j++)//          f[i][j] = min(f[i-1][j] , f[i-2][j-1] + cas[i]);//        cout<<f[n-1][k]<<endl;//      自己的做法:        memset(dp,0x3f3f3f3f,sizeof(dp));        dp[0][0][0] = 0;        dp[0][1][0] = 0x3f3f3f;        dp[0][1][1] = cas[1];        for(int i = 2 ; i < n ; i++)        {            for(int j = 1 ; j <= (i+1)/2 ; j++)            {                dp[1][j][0] = min(dp[0][j][0] , dp[0][j][1]);                dp[1][j][1] = dp[0][j-1][0] + cas[i];            }            for(int j = 1 ; j <= (i+1)/2 ; j++)            {                dp[0][j][0] = dp[1][j][0];                dp[0][j][1] = dp[1][j][1];            }        }    printf("%I64d\n",min(dp[0][k][1],dp[0][k][0]));    }}

原创粉丝点击