zoukankan      html  css  js  c++  java
  • HDU-1421 搬寝室(递推,DP,数学)2017寒假集训

    题意:从n个物品里挑出2k个物品,每次拿两个,花费是两物品重量的平方差,求最小的花费

    数据范围:2 <= 2*k <= n < 2000,重量不超过2^15

    思路:考虑有确定的2k个物品,确定一种顺序使花费最小

    可以证明,按重量对这2k个物品排序,然后相邻物品两两配对花费是最小的

    设总花费是(a-b) ^ 2 + (c-d) ^ 2 + .... etc,去括号得到a^2+b^2+...一串平方和为定值

    又当a<b<c<d时,ab+cd < ad+bc,就证明了这个结论

    考虑dp[i][j]表示前i个物品,取走了j对物品时的最小花费,对于每个i,决策有取这一对和不取这一对,转移为:dp[i][j] = min(dp[i-1][j], dp[i-2][j-1]+cost(i, i-1))

    答案为dp[n][k]

     1 #include<cstdio>
     2 #include<cstring>
     3 #include<algorithm>
     4 #define INF 0x3f3f3f3f
     5 using namespace std;
     6 
     7 const int mx = 1010;
     8 int a[mx*2], dp[2*mx][mx];
     9 
    10 int solve(int i, int j){
    11     int k = a[i]-a[j];
    12     return k*k;
    13 }
    14 
    15 int main(){
    16     int n, k;
    17     while (scanf("%d%d", &n, &k) == 2){
    18         memset(dp, INF, sizeof(dp));
    19         for (int i = 1; i <= n; i++){
    20             scanf("%d", &a[i]);
    21             dp[i][0] = 0;
    22         }
    23         dp[0][0] = 0;
    24         sort(a+1, a+n+1);
    25         for (int i = 2; i <= n; i++)
    26             for (int j = 1; j <= k; j++)
    27                 dp[i][j] = min(dp[i-1][j], dp[i-2][j-1]+solve(i, i-1));
    28         printf("%d
    ", dp[n][k]);
    29     }
    30     return 0;
    31 }
  • 相关阅读:
    图像的剪切
    DOS指令大全(二)
    扫描进程
    数据库名、数据库实例、全局数据库名、服务名、SID等的区别
    ORA29807: specified operator does not exist
    TCP/IP网络编程的几个网站
    漂在等待离职的日子(三)
    入职第一天
    入职一周
    漂在等待离职的日子(八)
  • 原文地址:https://www.cnblogs.com/QAQorz/p/9017021.html
Copyright © 2011-2022 走看看