ICode9

精准搜索请尝试: 精确搜索
首页 > 编程语言> 文章详细

三体攻击(蓝桥杯省赛2018C/C++A组第七题) 前缀和与差分优化

2022-02-09 22:06:34  阅读:182  来源: 互联网

标签:getindex int 三体 C++ 蓝桥 bS y1 y2 z1


题目:

题目描述:略

输入输出样例

示例

输入
2 2 2 3
1 1 1 1 1 1 1 1
1 2 1 2 1 1 1
1 1 1 2 1 2 1
1 1 1 1 1 1 2

输出
2

思路:
前置知识:前缀和与差分上前缀与差分下
三维前缀和公式:

S(x,y,z) = b(x,y,z) + S(x-1,y,z) + S(x,y-1,z) - S(x-1,y-1,z) + S(x,y,z-1) - S(x-1,y,z-1) - S(x,y-1,z-1) + S(x-1,y-1,z-1)​

方便记忆:
S(X,Y,Z)括号里面的"-"位置由二进制的"1"位置决定
加减运算符号由二进制总数"1"决定,若为奇数就(+)、为偶数就(-)

S(X, Y, Z) = a(X, Y, Z) + 表示
001 符号:+ S(X, Y, Z - 1)
010 符号:+ S(X, Y - 1, Z)
011 符号:- S(X, Y - 1, Z - 1)
100 符号:+ S(X - 1, Y, Z)
101 符号:- S(X - 1, Y, Z - 1)
110 符号:- S(X - 1, Y - 1, Z)
111 符号:+ S(X - 1, Y - 1, Z - 1)

三维差分操作 给(x1,y1,z1) 到 (x2,y2,z2) 加 h

void insert(int x1,int y1,int z1,int x2,int y2,int z2,int h)
{//对b数组执行插入操作,等价于对a数组中的(x1,y1,z1)到(x2,y2,z2)之间的元素都加上了h
    b(x1, y1, z1) +=h
	b(x1, y1, z2+1) -=h
	b(x1, y2+1, z1) -=h
	b(x1, y2+1, z2+1) +=h
	b(x2+1, y1, z1) -=h
	b(x2+1, y1, z2+1) +=h
	b(x2+1, y2+1, z1) +=h
	b(x2+1, y2+1, z2+1) -=h
}

代码:

#include<iostream>
#include<cstring>
using namespace std;
typedef long long LL;
const LL N=2e6+10;

int A,B,C,m;// 声明第一行参数, A层 B行 C列 m轮攻击
LL s[N],b[N],bS[N];// 声明战舰防御值数组、差分数组、前缀和数组

// 定义存放每轮攻击的7个参数结构体
struct Atk{
    int x1,y1,z1,x2,y2,z2,h;
}atk[N];

// 三维转为一维表示
int getindex(int i,int j,int k){
    return ((i - 1)*B + (j -1))*C + k;
}

// 三维差分操作
void insert(LL b[],int x1,int y1,int z1,int x2,int y2,int z2,int h){
    b[getindex(x1,y1,z1)] += h;
    b[getindex(x1,y1,z2+1)] -= h;
    b[getindex(x1,y2+1,z1)] -= h;
    b[getindex(x1,y2+1,z2+1)] += h;
    b[getindex(x2+1,y1,z1)] -= h;
    b[getindex(x2+1,y1,z2+1)] += h;
    b[getindex(x2+1,y2+1,z1)] += h;
    b[getindex(x2+1,y2+1,z2+1)] -= h;
}

// 检查是否爆炸函数
    // 将1~t轮攻击进行差分操作
    // 进行前缀和操作并判断
int check(int t){
    memcpy(bS,b,sizeof(bS));//将b赋值给bS
    
    for(int i=1;i <= t;i++){
        //构造差分函数
        insert(bS,atk[i].x1,atk[i].y1,atk[i].z1,atk[i].x2,atk[i].y2,atk[i].z2,atk[i].h);
    }

    for(int i = 1;i <= A;i++){
        for(int j = 1;j <= B;j++){
            for(int k = 1; k <= C; k++){//前缀和操作
                bS[getindex(i,j,k)] += bS[getindex(i,j,k -1)];
                bS[getindex(i,j,k)] += bS[getindex(i,j-1,k)];
                bS[getindex(i,j,k)] -= bS[getindex(i,j-1,k -1)];
                bS[getindex(i,j,k)] += bS[getindex(i-1,j,k)];
                bS[getindex(i,j,k)] -= bS[getindex(i-1,j,k -1)];
                bS[getindex(i,j,k)] -= bS[getindex(i-1,j-1,k)];
                bS[getindex(i,j,k)] += bS[getindex(i-1,j-1,k -1)];
                // cout<<bS[getindex(i,j,k)]<<endl;
                if(bS[getindex(i,j,k)] < 0){
                    return 1;
                }
            }
        }
    }
    return 0;
}


int main()
{
    cin>>A>>B>>C>>m;
    
    // 给大立方体的每个小方格赋值给防御值的同时初始化差分数组
    for(int i = 1;i <= A;i++){
        for(int j = 1;j <= B;j++){
            for(int k = 1; k <= C; k++){
                cin>>s[getindex(i,j,k)];//将三维坐标转为一维数组,同时初始化给防御值数组s[N]
                insert(b,i,j,k,i,j,k,s[getindex(i,j,k)]);
            }
        }
    }
    
  
    // 接收每次攻击时的7个参数
    for(int i=1; i <= m;i++){
        int x1,y1,z1,x2,y2,z2,h;
        //该死,这输入顺序bug调了半天
        cin>>x1>>x2>>y1>>y2>>z1>>z2>>h;
        atk[i] = {x1,y1,z1,x2,y2,z2,-h};
    }
    
    // 二分法进行判断是否爆炸
    int l=1,r=m;
    while(l < r){
        int mid = (l + r) >> 1;
        if(check(mid)){
            r = mid;
        }else{
            l = mid + 1;
        }
        
    }
    std::cout << l << std::endl;//最后l是等于r 
    return 0;
}

知识点总结:

  1. 三维前缀和
  2. 三维差分操作
  3. 二分查找

标签:getindex,int,三体,C++,蓝桥,bS,y1,y2,z1
来源: https://blog.csdn.net/weixin_40934238/article/details/122850375

本站声明: 1. iCode9 技术分享网(下文简称本站)提供的所有内容,仅供技术学习、探讨和分享;
2. 关于本站的所有留言、评论、转载及引用,纯属内容发起人的个人观点,与本站观点和立场无关;
3. 关于本站的所有言论和文字,纯属内容发起人的个人观点,与本站观点和立场无关;
4. 本站文章均是网友提供,不完全保证技术分享内容的完整性、准确性、时效性、风险性和版权归属;如您发现该文章侵犯了您的权益,可联系我们第一时间进行删除;
5. 本站为非盈利性的个人网站,所有内容不会用来进行牟利,也不会利用任何形式的广告来间接获益,纯粹是为了广大技术爱好者提供技术内容和技术思想的分享性交流网站。

专注分享技术,共同学习,共同进步。侵权联系[81616952@qq.com]

Copyright (C)ICode9.com, All Rights Reserved.

ICode9版权所有