zoukankan      html  css  js  c++  java
  • bzoj4716 假摔

    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的火力最低值。
    可以转化为用类似dijkstra求最短路的方法求出离起点最近的k个点,即先把最小的符合要求的矩形(x1,y1,x2,y2)放入堆中,每次出堆时扩展出比其长/宽多1且未入堆的矩形(x1,y1,x2+1,y2)和(x1,y1,x2,y2+1),第k次出堆的矩形的总和+1即为答案
    #include<cstdio>
    #include<queue>
    const int R=1e7,P=2939999;
    char buf[R],*ptr=buf-1;
    int _(){
        int x=0,c=*++ptr;
        while(c<48)c=*++ptr;
        while(c>47)x=x*10+c-48,c=*++ptr;
        return x;
    }
    typedef unsigned long long u64;
    int n,m,n1,m1,k,ans=0;
    int s[1007][1003];
    u64 hs[P];
    struct node{
        int v,x1,y1,x2,y2;
    };
    bool operator<(const node&a,const node&b){
        return a.v>b.v;
    }
    std::priority_queue<node>q;
    inline void push(int x1,int y1,int x2,int y2){
        if(x1<0||y1<0||x2>n||y2>m)return;
        u64 hv=(u64(x1<<10|y1)<<10|x2)<<10|y2;
        int w=hv%P;
        while(hs[w]){
            if(hs[w]==hv)return;
            if((w+=1237)>=P)w-=P;
        }
        hs[w]=hv;
        int v=s[x1][y1]+s[x2][y2]-s[x1][y2]-s[x2][y1];
        q.push((node){v,x1,y1,x2,y2});
    }
    int main(){
        fread(buf,1,R,stdin);
        n=_();m=_();n1=_();m1=_();k=_();
        for(int i=1;i<=n;++i){
            for(int j=1;j<=m;++j)s[i][j]=_()+s[i][j-1];
            for(int j=1;j<=m;++j)s[i][j]+=s[i-1][j];
        }
        for(int i=n1;i<=n;++i){
            for(int j=m1;j<=m;++j){
                push(i-n1,j-m1,i,j);
            }
        }
        while(k--){
            node w=q.top();q.pop();
            ans=w.v;
            push(w.x1,w.y1,w.x2+1,w.y2);
            push(w.x1,w.y1,w.x2,w.y2+1);
        }
        printf("%d",ans+1);
        return 0;
    }
  • 相关阅读:
    [工作中的设计模式]中介模式模式Mediator
    [工作中的设计模式]责任链模式chain
    [工作中的设计模式]迭代子模式Iterator
    [工作中的设计模式]组合模式compnent
    TI IPNC Web网页之流程分析
    TI IPNC Web网页之GoDB开发环境
    安装ubuntu时将boot目录单独挂载的意义
    ubuntu添加自定义vga输出分辨率
    GCC编译默认的头文件搜索路径
    设置搜狗输入法在任何时候按左右两侧的shift激活
  • 原文地址:https://www.cnblogs.com/ccz181078/p/6052228.html
Copyright © 2011-2022 走看看