• bzoj4716: 假摔


    BZOJ4716: 假摔

    Time Limit: 20 Sec  Memory Limit: 512 MB
    Submit: 10  Solved: 7
    [Submit][Status][Discuss]

    Description

    【题目背景】
    小Q最近喜欢上了一款游戏,名为《舰队connection》,在游戏中,小Q指挥强大的舰队南征北战,从而成为了一名
    dalao。在游戏关卡的攻略中,可能由于作战过程中某艘船受到严重损伤,为避免沉没而被迫进行返航,这种情况
    大家称为这艘船“假摔”。小Q最喜欢使用的一艘战舰代号为P01,但是最近这艘船总是用各种不同的姿势假摔,于
    是小Q打算研究一下原因。
    【题意描述】
    P01的装甲可以近似看作一个n*m的矩阵,每个位置上的数字代表这个位置装甲的强度。当受到炮击时,防御力为被
    炮击的部分的所有位置强度之和。最近小Q发现,敌方有一种船只被称为ENE,它可以发射不同形状的炮弹,以达到
    攻击装甲最薄弱处的目的。P01已经被连续k次用不同方式打成了严重损伤(假摔),于是小Q打算分析一下ENE的攻击
    力。为了简单起见,我们作如下假设:
    1、ENE的炮弹形状无论如何变化,火力值都为一个定值(整数,未知)
    2、ENE的炮弹形状只能是长方形(ENE:呵呵),且由于口径的限制,炮弹不能太小(具体来说,对于每一发炮弹长xi
    宽yi,有xmin<=xi<=n,ymin<=yi<=m)
    3、当ENE的炮击命中P01的某处装甲时,被命中部分的强度之和为P01的防御力,此时,ENE的火力必须严格大于P01
    的防御力,才能将其击穿并造成严重损伤(假摔)。
    然而,小Q并没有得到详细的中弹数据,只知道P01用k种不同的方式假摔过。两种假摔方式不同,当且仅当受到炮
    击的位置不完全相同。因此,不同形状的炮弹击穿护甲时必定可以造成不同的假摔方式,而相同形状的炮弹在不同
    的位置击穿护甲也能造成不同的假摔方式。现在,小Q想估计ENE的火力最低是多少。于是,这个任务被交给了你。
    举例而言,假设P01的护甲为3*4:
    0 1 3 7
    1 1 5 5
    7 6 9 6
    如果ENE的口径至少为2*2,那么直接使用2*2的炮弹攻击左上角2*2的装甲时,只要火力>=4即可造成一种假摔。如
    果想造成k=3种不同的假摔方式,至少要拥有12的火力,此时可以造成如下三种假摔方式:
    1、2*2炮弹,攻击有数字的部分,装甲值为3
    0 1 - -
    1 1 - -
    - - - -
    2、2*2炮弹,攻击有数字的部分,装甲值为10
    - 1 3 -
    - 1 5 -
    - - - -
    3、2*3炮弹,攻击有数字的部分,装甲值为11
    0 1 3 -
    1 1 5 -
    - - - -
    可以证明,火力小于12时,无法造成3种不同的假摔方式,所以ENE的火力至少应为12。
     

    Input

    第一行,五个数n, m, xmin, ymin, k,空格分隔。
    接下来n行,每行m个数,空格分隔,表示P01的装甲。
    1<=n,m<=1000,1<=xmin<=n, 1<=ymin<=m, 1<=k<=250000,装甲值为不超过2000的非负整数。
    保证火力为无穷大的ENE可以造成k种不同的假摔方式。
     

    Output

    仅一行,一个数,表示ENE的火力最低值。
     

    Sample Input

    3 4 2 2 3
    0 1 3 7
    1 1 5 5
    7 6 9 6

    Sample Output

    12

    HINT

     

    Source

     题意:求第K大的长和宽在指定范围内的矩阵的权值和
    用优先队列维护当前权值和最小的矩阵 然后弹K次 把多一行或者是多一列的矩阵扔进优先队列
    判重的话用map或hash都行...
    复杂度大概是O(Klognm)
    注意map的==是用!(a>b||a<b) 实现的...所以重载自定义比较符的时候不能只比较矩阵权值和
    身败名裂系列....
     1 #include<bits/stdc++.h>
     2 #define rep(i,l,r) for(int i=l;i<=r;++i)
     3 using namespace std;
     4 const int N=1025;
     5 int sum[N][N],n,m,ln,lm,K,s[N][N],ans,cnt;
     6 struct zs{
     7     int a,b,c,d,v;
     8 };
     9 bool operator < (zs a,zs b){
    10     if(a.v!=b.v) return a.v>b.v;
    11     if(a.a!=b.a) return a.a>b.a;
    12     if(a.b!=b.b) return a.b>b.b;
    13     if(a.c!=b.c) return a.c>b.c;
    14     if(a.d!=b.d) return a.d>b.d;
    15     return 0;
    16 }
    17 inline int get(int a,int b,int c,int d){
    18     return sum[c][d]-sum[a-1][d]-sum[c][b-1]+sum[a-1][b-1];
    19 }
    20 priority_queue<zs> q;
    21 map<zs,int> mp;
    22 int main(){
    23     scanf("%d%d%d%d%d",&n,&m,&ln,&lm,&K);
    24     rep(i,1,n) rep(j,1,m) scanf("%d",&s[i][j]);
    25     rep(i,1,n) rep(j,1,m) sum[i][j]=sum[i-1][j]+sum[i][j-1]-sum[i-1][j-1]+s[i][j];
    26     rep(i,1,n-ln+1) rep(j,1,m-lm+1) q.push((zs){i,j,i+ln-1,j+lm-1,get(i,j,i+ln-1,j+lm-1)});
    27     while(!q.empty()){
    28         zs x=q.top(); q.pop();
    29         if(mp.find(x)!=mp.end()) continue;
    30         mp[x]=1; ++cnt;
    31         ans=x.v;
    32         if(cnt==K) break;
    33         if(x.c+1<=n) q.push((zs){x.a,x.b,x.c+1,x.d,get(x.a,x.b,x.c+1,x.d)});
    34         if(x.d+1<=m) q.push((zs){x.a,x.b,x.c,x.d+1,get(x.a,x.b,x.c,x.d+1)});
    35     }
    36     printf("%d
    ",ans+1);
    37 }
    View Code
     
  • 相关阅读:
    面向对象课程第三次博客总结
    面向对象课程多线程总结
    23种设计模式整理
    java中synchronized与lock的理解与应用
    关于MySQL查询优化
    mysql操作规范建议
    Linux中实体链接与符号链接详解
    获取本地ipv4地址方法(go语言)
    分库分表与负载均衡的一致性hash算法
    golang闭包的一个经典例子
  • 原文地址:https://www.cnblogs.com/Bloodline/p/6052191.html
Copyright © 2020-2023  润新知