zoukankan      html  css  js  c++  java
  • Codeforces 229D Towers

    http://codeforces.com/problemset/problem/229/D

    题意:有n(1<=n<=5,000)座塔排在一条直线上,从左到右每个塔的高度分别为hi(1<=hi<=100,000),每次操作你可以选择一座塔(假设是第i座),用吊车把它吊起来,然后放到与它相邻的一座塔上(可以是第i-1座也可以是第i+1座),这样,新塔的高度为两座塔的和,完成操作后,塔的总数减少一座。问最少需要多少次操作可以使得所有的塔从左到右形成一个非递减序列。

    思路:

    我们可以这样设计dp:f[i][j]=min(f[j-1][k]+i-j-1)这是n^3的转移

    我们发现如果以某个位置为末尾,那么一定是当前"块"里面"块"的高度最小的时候就是最优解,所以我们的转移从n^2变成了n   

    而枚举状态的效率是O(n),总的就是O(n^2)

     1 #include<cstdio>
     2 #include<cmath>
     3 #include<algorithm>
     4 #include<cstring>
     5 #include<iostream>
     6 int n,a[200005],sum[200005];
     7 int mn[200005],pd[200005],num[200005];
     8 int read(){
     9     int t=0,f=1;char ch=getchar();
    10     while (ch<'0'||ch>'9'){if (ch=='-') f=-1;ch=getchar();}
    11     while ('0'<=ch&&ch<='9'){t=t*10+ch-'0';ch=getchar();}
    12     return t*f;
    13 }
    14 int main(){
    15     n=read();
    16     for (int i=1;i<=n;i++) a[i]=read();
    17     for (int i=1;i<=n;i++) sum[i]=sum[i-1]+a[i];
    18     for (int i=1;i<=n;i++){
    19         if (i==1){
    20             mn[1]=0;
    21             num[1]=a[1];
    22             continue;
    23         }
    24         bool flag=0;mn[i]=0x3f3f3f3f;
    25         for (int j=i;j>=1;j--){
    26            if (num[j-1]<=sum[i]-sum[j-1]&&mn[i]>mn[j-1]+i-j){
    27                 mn[i]=mn[j-1]+i-j;
    28                 flag=1;
    29                 num[i]=sum[i]-sum[j-1];
    30            }    
    31         }
    32         if (flag) continue;
    33         mn[i]=i-1;
    34         num[i]=sum[i];
    35     }
    36     return 0;
    37 }
  • 相关阅读:
    Ubuntu 下Apache安装和配置
    MariaDB二进制包简单安装部署
    Ubuntu下MongoDB的安装和使用
    Linux文件类型及目录配置
    centos7下挂载U盘和移动硬盘
    详解 比特(位,bit),字节(Byte),字符的区别 *(转)
    Socket使用及简单实例
    缓存
    字体小图标记录
    大流量下的兜底容灾方案
  • 原文地址:https://www.cnblogs.com/qzqzgfy/p/5621599.html
Copyright © 2011-2022 走看看