hdu 1421 dp 入门题

来源:互联网 发布:淘宝店铺怎么改名字啊 编辑:程序博客网 时间:2024/05/16 17:28

http://acm.hdu.edu.cn/showproblem.php?pid=1421

中文题

思路:首先要找出怎么将所有的物品组合成一对一对的,题目要求疲劳之最小,也就是一对之中两个物品的重量的差距最小。那么就需要运用排序了,将物品从小到大排序,从遍历物品直到倒数第二个,将每一个物品和下一个物品组合成一对,这样就会发现如果我们先选了这一对,那么下一对就不可以选了,因为两者中有一个元素是重复的。

大概理清思路之后发现状态定义不出来。。。不知道怎么样才保证他是k对。。。dp果然得慢慢来,慢慢培养自己的感觉吧。

定义状态:dp[i][j]表示从i件物品中选取出j对来

分成两种情况,一种是不选当前对dp[i][j] = dp[i-1][j],一种是选当前对 dp[i][j] = dp[i-2][j-1]+a[i-1]

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

代码:

#include <iostream>#include <cstdio>#include <cstring>#include <algorithm>using namespace std;#define M 2009#define INF 0x3f3f3f3fint a[M];int dp[M][M]; // dp[i][j]表示从i件物品中选取出j对来int main(){    int n,k;    while(scanf("%d %d",&n,&k)==2)    {        for(int i = 1;i <= n;i++)            scanf("%d",&a[i]);        sort(a+1,a+n+1);//从小到大排使得差距最小        for(int i = 1;i <= n-1;i++)            a[i] = (a[i]-a[i+1])*(a[i]-a[i+1]); //计算出每一对的疲劳度        for(int i = 1;i <= n;i++)        for(int j = 0;j <= n;j++)        {            dp[i][j] = INF;   //由于是找出最小值所以赋初值为INF        }        for(int i = 1;i <= n;i++)        {            dp[i][0] = 0;  //从i件中选取0对的话疲劳值肯定为0            for(int j = 0;2*j <= i;j++)            {                if(i==1) dp[i][j] = dp[i-1][j]; //特殊情况                else dp[i][j] = min(dp[i-1][j],dp[i-2][j-1]+a[i-1]);            }        }        printf("%d\n",dp[n][k]);    }    return 0;}


0 0
原创粉丝点击