zoukankan      html  css  js  c++  java
  • [CodeForces-797F]Mice and Holes

    题目大意:
      在一条直线上,有n个老鼠,m个洞。
      每个老鼠i都有一个初始位置x[i]。
      每个洞i都有一个固定位置p[i]和容量限制c[i]。
      求所有老鼠都进洞的最小距离总和。

    思路:
      动态规划。
      用f[i][j]表示前i个洞、前j只老鼠的最小距离总和。
      用sum[i][j]表示前j个老鼠都进入第i个洞的距离总和。
      可以得到以下DP方程:
      f[i][j]=min{f[i-1][k]-sum[i][k]|k<=j}+sum[i][j]。
      然后就MLE,发现sum可以每次求出来,f如果倒着推,也可以省掉一维。
      这样空间复杂度就是O(n)的,时间复杂度是O(n^2m)的,在第42个点TLE了。
      考虑使用单调队列维护f[i-1][k]-sum[i][k]的min,做到O(nm)。

     1 #include<deque>
     2 #include<cstdio>
     3 #include<cctype>
     4 #include<algorithm>
     5 inline int getint() {
     6     register char ch;
     7     register bool neg=false;
     8     while(!isdigit(ch=getchar())) if(ch=='-') neg=true;
     9     register int x=ch^'0';
    10     while(isdigit(ch=getchar())) x=(((x<<2)+x)<<1)+(ch^'0');
    11     return neg?-x:x;
    12 }
    13 const long long inf=0x7fffffffffffffffll;
    14 const int N=5001;
    15 int x[N];
    16 struct Hole {
    17     int p,c;
    18     bool operator < (const Hole &another) const {
    19         return p<another.p;
    20     }
    21 };
    22 Hole h[N];
    23 long long f[2][N],sum[N];
    24 std::deque<int> q;
    25 int main() {
    26     int n=getint(),m=getint();
    27     for(register int i=1;i<=n;i++) {
    28         x[i]=getint();
    29     }
    30     for(register int i=1;i<=m;i++) {
    31         h[i]=(Hole){getint(),getint()};
    32     }
    33     std::sort(&x[1],&x[n+1]);
    34     std::sort(&h[1],&h[m+1]);
    35     std::fill(&f[0][1],&f[0][n+1],inf);
    36     for(register int i=1;i<=m;i++) {
    37         for(register int j=1;j<=n;j++) { 
    38             sum[j]=sum[j-1]+std::abs(h[i].p-x[j]); 
    39         }
    40         q.clear();
    41         q.push_back(0);
    42         for(register int j=1;j<=n;j++) {
    43             while(!q.empty()&&j-q.front()>h[i].c) {
    44                 q.pop_front();
    45             }
    46             while(!q.empty()&&f[!(i&1)][j]-sum[j]<=f[!(i&1)][q.back()]-sum[q.back()]) {
    47                 q.pop_back();
    48             }
    49             q.push_back(j);
    50             f[i&1][j]=f[!(i&1)][q.front()]+sum[j]-sum[q.front()];
    51         }
    52     }
    53     printf("%I64d
    ",f[m&1][n]!=inf?f[m&1][n]:-1);
    54     return 0;
    55 }
  • 相关阅读:
    Linq to sql(四):查询句法(一)
    (转帖)用戶控件包裝器的设计与实现
    iptables 安装设置 针对游戏服务器
    Shell脚本加密
    Nginx配置文件nginx.conf中文详解
    C#获取默认浏览器的完整地址并在默认浏览器中打开对应的url地址
    HttpWebRequest类
    解决问题记录(3)-事务处理出错:连接打开但是在fetching状态中。
    程序生涯的几个感悟
    解决问题记录(4)-Oracle Not Support Parallel Transaction
  • 原文地址:https://www.cnblogs.com/skylee03/p/7675917.html
Copyright © 2011-2022 走看看