zoukankan      html  css  js  c++  java
  • Codeforces 13C(DP)

    题意:给出一个数列长度小于5000,每次操作将数列中的数加1或减1,问最少需要多少步操作可以得到一个不降序列;

    分析:可知最少的次数,一定是由原来的数据构成的(据说可以用反证法证),即有原来的数组成的不降子序列中有一个最小的情况;

      我们用F[i][j] = min(F[i][j -1] (不包含这一个时),F[i-1][j] + fabs(A[i] - B[j])(包含这一种时));其中B[]代表不重非减序列i,j代表前个数最大为B[j]时的最优情况;

    注意:本题数据大,F[][]的过程用到了滚动数组;

     1 #include <stdio.h>
     2 #include <string.h>
     3 #include <stdlib.h>
     4 #include <math.h>
     5 int A[5001],B[5001],C[5001];
     6 __int64 F[3][5001];
     7 __int64 min(__int64 a,__int64 b)
     8 {
     9     return a > b ? b:a;
    10 }
    11 int cmp(const void *a,const void *b)
    12 {
    13     return *(int *)a - *(int *)b;
    14 }
    15 int main()
    16 {
    17     int n,m,i,j,a,b;
    18     scanf("%d",&n);
    19     for(i = 1;i <= n;i ++)
    20     {
    21         scanf("%d",&A[i]);
    22         C[i] = A[i];
    23     }
    24     qsort(C + 1, n, sizeof(C[0]), cmp);
    25     B[1] = C[1];
    26     m = 1;
    27     for(i = 2; i<= n;i ++)
    28     if(C[i] > B[m])
    29     {
    30         ++ m;
    31         B[m] = C[i];
    32     }
    33     F[1][1] = fabs(A[1] - B[1]);
    34     for(i = 2;i <= m;i ++)
    35         F[1][i] = min(F[1][i -1],fabs(A[1] - B[i]));
    36     for(i = 2;i <= n;i ++)
    37         {
    38             F[i&1][1] = F[1 - (i&1)][1] + fabs(A[i] - B[1]);
    39             for(j = 2;j <= m;j ++)
    40         F[i&1][j] = min(F[i&1][j - 1],F[1 - i&1][j] + fabs(A[i] - B[j]));
    41         }
    42     printf("%I64d",F[n&1][m]);
    43     return  0;
    44 }
    View Code
  • 相关阅读:
    Permutations II
    N-Queens II
    Palindrome Number
    Minimum Path Sum
    JS的DOM操作2
    JS 的DOM操作
    函数概念
    JavaScript数组
    JavaScript循环及练习
    JS语言
  • 原文地址:https://www.cnblogs.com/AHU-songyuan2235/p/3356182.html
Copyright © 2011-2022 走看看