• poj Finicky Grazers 3184 夜


    http://poj.org/problem?id=3184

    动态规划 加各种优化

    二维数组太大 需要用滚动数组

    题目大意: 给你N头牛 和(0--L)L+1个位置 在满足牛之间距离最大化的前提下

    移动牛花费时间最少

    首先第一头牛必须在 0 这个位置 第N 头牛必须在 L 这个位置

    D=L/(N-1);

    如果L%(N-1) 余数不为 0 时 存在 D+1

    本题关键在于 每头牛所在位置 都有一定的范围

    用函数 findlr(int i,int &l,int &r)求范围 i代表第几头牛 l和r分别为左右边界

    其他详情见代码注释

    #include<iostream>
    #include<string>
    #include<stdio.h>
    #include<cstring>
    #include<algorithm>
    #include<vector>
    #include<cmath>
    using namespace std;

    #define MAX 0xfffffff
    #define MAXN 10005
    #define MAXL 100005
    int location[MAXN];
    int moveto[2][MAXL];//滚动数组
    int D,D1;//D1为(D+1)如果为-1 则代表(D+1)不存在
    int N,L;
    inline void findlr(int i,int &l,int &r)//求每头牛的边界
    {
           if(i<N)
           {
               l=D*(i-1);
               if(D1!=-1&&(L-(D1*(N-i)))>l)
               {
                   l=(L-(D1*(N-i)));
               }
               r=L-(D*(N-i));
               if(D1!=-1&&(D1*(i-1))<r)
               {
                   r=(D1*(i-1));
               }
           }
           else//最后一头牛位置确定
           {
               l=r=L;
           }
    }
    int main()
    {
        scanf("%d%d",&N,&L);
        for(int i=1;i<=N;++i)
        {
            scanf("%d",&location[i]);
        }
        if(N==1)
        {
            printf("0\n");
            return 0;
        }
        D=L/(N-1);
        if(L%(N-1))
        {
            D1=D+1;
        }
        else
        {
            D1=-1;
        }
        for(int i=0;i<2;++i) //先初始化最大
        {
            for(int j=0;j<=L;++j)
            {
                moveto[i][j]=MAX;
            }
        }
        int l,r,l1,r1;
        moveto[1][0]=abs(location[1]-0);//第一头牛位置提前求出来
        for(int i=2;i<=N;++i)//从第二头牛开始求
        {
           findlr(i,l,r);//发现的i头牛所在位置范围
           for(int j=l;j<=r;++j)
           {
              moveto[i%2][j]=moveto[(i-1)%2][j-D]+abs(location[i]-j);
              if(D1!=-1&&j-D1>=0)//存在第二种可能(j-D1)是防止小于0而越界
              {
                 moveto[i%2][j]=min(moveto[i%2][j],moveto[(i-1)%2][j-D1]+abs(location[i]-j));
              }
           }
           if(i>3)
           {
               findlr(i-2,l1,r1);//由于用了滚动数组 i和(i-2)所用的一样 所用需要将i所在范围以外的进行初始化回避(i-2)的影响
               for(int w=l1;w<=r1;++w)
               {
                   if(w<l||w>r)
                   {
                       moveto[i%2][w]=MAX;
                   }
               }
           }
        }
        printf("%d\n",moveto[N%2][L]);
        return 0;
    }

  • 相关阅读:
    Xaml引用图片路径的方式
    并发概念模型:JMM(JAVA内存模型)
    并发组件之一:ThreadLocal线程本地变量
    并发锁之二:ReentrantReadWriteLock读写锁
    并发锁之一:ReentrantLock重入锁
    AQS同步队列器之二:等待通知机制
    AQS同步队列器之一:使用和原理
    css常用操作
    自动生成mybatis代码
    jdk动态代理源码分析(二)---依赖接口的实现
  • 原文地址:https://www.cnblogs.com/liulangye/p/2437353.html
Copyright © 2020-2023  润新知