zoukankan      html  css  js  c++  java
  • hdu 5190 Building Blocks

    问题描述
    看完电影后,乐乐回家玩起了积木。
    他已经搭好了n堆积木,他想通过调整积木,使得其中有连续W堆积木具有相同的高度,同时他希望高度恰好为H。
    乐乐的积木都这了,也就是说不能添加新的积木,只能移动现有的积木。
    他可以把一个积木从一堆移动到另一堆或者新的一堆,但是不能移动到两堆之间。比如,一次移动之后,"3 2 3" 可以变成 "2 2 4" 或者 "3 2 2 1",但是不能变成"3 1 1 3".
    请你帮他算算,需要移动的最少积木数。
    输入描述
    有多组测试数据,大约100组。
    第一行三个整数,nWHn表示有多少堆积木。
    第二行n个元素,表示这n座积木的高度。
    所有数据的范围[1,50000];
    输出描述
    输出最少需要移动的次数,如果无法完成输出-1。
    输入样例
    4 3 2
    1 2 3 5
    4 4 4
    1 2 3 4
    输出样例
    1
    -1

    题目分析:

    枚举最终的W堆积木在哪,确定了区间,那么就需要把高于H的拿走,低于H的补上,高处的积木放到矮的上面,这样最优。因此把这个区间变成W*H的代价就是max((HiH),(HHj))(HiH,HjH)即在把高的变矮和把矮的变高需要的移动的积木数
    取较大的。从第一个区间[1,W]到第二区间[2,W+1]只是改变了2堆积木,可以直接对这两堆积木进行删除和添加来维护(HiH)(HHj)。
    需要注意的是,最终选取的W堆积木中,有可能有几堆原本不存在。如 9 8 7 形成3*3,可把3堆积木变成5堆 3 3 3 8 7,最少移动6个积木。因此需要在n堆积木两端补上W个0。整个问题的复杂度是O(n+W).

    #include<cstdio>
    #include<cstring>
    #include<iostream>
    #include<algorithm>
    #include<cmath>
    #define maxn 150010
    #define INF 10000000
    using namespace std;
    typedef long long LL;
    LL a[maxn],n;
    int main()
    {
    LL w,h;
    int num;
    while(scanf("%I64d %I64d %I64d",&n,&w,&h)!=EOF)
    {
    memset(a,0,sizeof(a));
    LL sum=0;
    for(int i=w+1; i<=n+w; i++)
    {
    scanf("%I64d",&a[i]);
    sum+=a[i];
    }
    if(sum<w*h)
    printf("-1 ");
    else
    {
    LL sum_c=0,sum_r=w*h;
    LL ans=sum_r;
    for(int i=2; i<=w+n+1; i++)
    {
    if(a[i-1]<h)
    sum_r-=h-a[i-1];
    else
    sum_c-=a[i-1]-h;
    if(a[i+w-1]<h)
    sum_r+=h-a[i+w-1];
    else
    sum_c+=a[i+w-1]-h;
    //printf("%I64d %I64d ",sum_r,sum_c);
    ans=min(ans,max(sum_r,sum_c));
    }
    printf("%I64d ",ans);

    }
    }
    return 0;
    }



  • 相关阅读:
    数据库设计:数据库设计步骤,er图,三大范式
    连接查询
    连接查询和分组查询
    Django项目的创建与配置
    WEB框架的原理总结
    RabbitMQ---消息队列
    Djang之基于角色的权限控制(RBAC)
    Django之基于RBAC权限控制生成动态菜单
    关于装饰器的一些小练习
    关于简单的python函数的一些小练习题
  • 原文地址:https://www.cnblogs.com/tsw123/p/4363817.html
Copyright © 2011-2022 走看看