zoukankan      html  css  js  c++  java
  • HDU1421:搬寝室(线性dp)

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

    又是一道,没有思想的题,看了题解,我发现我的dp题几乎都看了题解,我总是想不好状态转移方程,汗颜,以后怎么比赛啊。

    先排序,然后说一个数学问题。

    首先,要怎么搬呢?即每一对要怎么取?如果有abcd四个数,且a<b<c<d,应该是取ab,cd好呢还是ac,bd好?抑或是bc,ad好呢?答案是第一种,因为:

    (a-b)^2+(c-d)^2 < (a-c)^2+(b-d)^2
    (a-b)^2+(c-d)^2 < (a-d)^2+(b-c)^2

    即每对物品都应是重量最为接近的物品,也就是说对n件物品排序后,每对物品都应该是连续的

    定义数组w[i]为搬第i对物品所消耗的疲劳值;数组dp[n][k]来表示在n件物品中搬k对的最佳状态,而达到这一状态的决策可能为:

    1. 第n件物品不搬,即在前n - 1件物品中搬k对,那么疲劳值仍为dp[n - 1][k];
    2. 第n件物品要搬,那么根据上面所证,第n - 1件物品也要同时搬,即在前n - 2件物品中搬k - 1对物品,再搬最后一对物品,那么疲劳值为dp[n - 2][k - 1] + w[n - 1]。

    为使疲劳值最小,因此最佳策略为取两种决策中的最小值,即应使:

    dp[n][k] = min(dp[n - 1][k], dp[n - 2][k - 1] + w[n - 1])

    应该注意的是要考虑边界问题,dp[i][j]中:

    1. 当2 * j > i时,即要搬的数量超过了物品总量,这是不可能发生的,因此此时令dp[i][j]为无穷大;
    2. 当j == 0时,即在一对物品都没搬时,所需疲劳值应该是0,此时令dp[i][j] = 0。
    #include <iostream>
    #include <stdio.h>
    #include <string.h>
    #include <algorithm>
    #include <queue>
    #include <math.h>
    #define inf 0x3f3f3f3f
    typedef long long ll;
    using namespace std;
    int n,k,w[2010],dp[2010][1010];
    
    int main()
    {
        while(scanf("%d%d",&n,&k)!=EOF)
        {
            for(int i=1;i<=n;i++)
            {
                scanf("%d",&w[i]);
            }
            sort(w+1,w+1+n);
            for(int i=1;i<n;i++)
            {
                w[i]=w[i+1]-w[i];
                w[i]=w[i]*w[i];
            }
            for(int i=0;i<=n;i++)
            {
                for(int j=0;j<=k;j++)
                {
                    dp[i][j]=inf;
                }
            }
            for(int i=0;i<=n;i++)
            dp[i][0]=0;      //边界的处理
            for(int i=2;i<=n;i++)
            {
                for(int j=1;j*2<=i;j++)
                {
                    dp[i][j]=min(dp[i-2][j-1]+w[i-1],dp[i-1][j]);
                }
            }
            printf("%d
    ",dp[n][k]);
        }
        return 0;
    }
  • 相关阅读:
    [LeetCode] Merge Interval系列,题:Insert Interval,Merge Intervals
    [LeetCode] Simplify Path,文件路径简化,用栈来做
    [LeetCode] Sort Colors 对于元素取值有限的数组,只遍历一遍的排序方法
    [LeetCode] Largest Rectangle in Histogram O(n) 解法详析, Maximal Rectangle
    实现一个协程版mysql连接池
    Linux搭建kafka
    PHP信号管理
    virtual memory exhausted: Cannot allocate memory
    RSA 非对称加密,私钥转码为pkcs8 错误总结
    Git Flow 工作模型与使用
  • 原文地址:https://www.cnblogs.com/zhangmingcheng/p/4372900.html
Copyright © 2011-2022 走看看