• CF 351A


    http://codeforces.com/problemset/problem/351/C

    题意:有2*n个浮点数a1,a2,a3...a2*n,把他们分成n队,对于每对<A,B>,对A做floor() 操作,对B 做ceil()操作。生成b1...b2*n, 求|(b1+b2+...+b2*n)-(a1+a2+a3...+a2*n)|的最小值。

    对于每个数ai,对他们做floor()的cost是up()=ai-floor(ai) ,做ceil()的cost是down()=ceil(ai)-ai

    设f[i][j]表示前i个节点有j个做ceil()操作(i-j个floor())的最优值

      f[i][j]=min{f[i-1][j-1]+up(a[i]),   对ai做up()的代价

            f[i-1][j]+down(a[i])}   对ai做down()的代价、

      当i == j时注意f[i-1][j]不存在这种情况.

       这里的min{}里面比较的是绝对值。、

    临界值f[0][0]=0; f[0][1]=0;目标答案|f[2*n][n]|。

    #include <stdio.h>
    #include <string.h>
    #include <math.h>
    #define N 2001
    double min(double a,double b)
    {
        return fabs(a)>fabs(b)? b:a;
    }
    double up(double x)
    {
        return ceil(x)-x;
    }
    double down(double x)
    {
        return x-floor(x);
    }
    double a[2*N+5];
    double f[2*N+5][N+5];
    int main()
    {
        int i,j,m,n;
        while (scanf("%d",&n)!=EOF)
        {
            for (i=1;i <=2*n; i++)
                scanf("%lf",&a[i]);
            f[0][0]=0;
            f[0][1]=0;
           double tmp;
            for (i=1;i<=2*n; i++)
                for (j=0; j<= n && j<=i;j++)
                {
                    tmp=400000000;
                    if (i>j) tmp=f[i-1][j]+down(a[i]);
                    if (j>0)
                        tmp=min(tmp,f[i-1][j-1]-up(a[i]));
                        f[i][j]=tmp;
                }
    
                printf("%0.3lf
    ",fabs(f[2*n][n]));
        }
        return 0;
    }

    好吧,其实仔细看看就是一个背包。

      我们可以把i 这个维度,在空间上优化点。跟0/1背包似的。

         f[j]=min{f[j-1]+up(a[i]),f[j]+down(a[i])}

    不过j循环得downto了,因为f[j-1]在迭代前,还应该是f[i-1][j-1]这个状态,而不是f[i][j-1]了。

    #include <stdio.h>
    #include <string.h>
    #include <math.h>
    #define N 2001
    //#define min(a,b) a>b?b:a
    double min(double a,double b)
    {
        return fabs(a)>fabs(b)? b:a;
    }
    double up(double x)
    {
        return ceil(x)-x;
    }
    double down(double x)
    {
        return x-floor(x);
    }
    double a[2*N+5];
    double f[N+5];
    int main()
    {
        int i,j,m,n;
        while (scanf("%d",&n)!=EOF)
        {
            for (i=1;i <=2*n; i++)
                scanf("%lf",&a[i]);
            f[0]=0; f[1]=0;
           double tmp;
            for (i=1;i<=2*n; i++)
                for (j=min(i,n);j>=0;j--)
                {
                    tmp=400000000;
                    if (i>j) tmp=f[j]+down(a[i]);
                    if (j>0)
                        tmp=min(tmp,f[j-1]-up(a[i]));
                        f[j]=tmp;
                    //f[i][j]=min(f[i-1][j-1]+up(a[i]),f[i-1][j]+down(a[i]));
                }
                printf("%0.3lf
    ",fabs(f[n]));
        }
        return 0;
    }
  • 相关阅读:
    28.数组中出现次数超过长度一半的数字(python)
    [leetcode] 145. 二叉树的后序遍历
    [leetcode] 144. 二叉树的前序遍历
    [leetcode] 94. 二叉树的中序遍历
    [leetcode] 93. 复原IP地址
    [leetcode] 206. 反转链表
    [leetcode] 92. 反转链表 II
    [leetcode] 91. 解码方法
    [leetcode] 90. 子集 II.md
    [leetcode] 88. 合并两个有序数组
  • 原文地址:https://www.cnblogs.com/six-god/p/3353608.html
Copyright © 2020-2023  润新知