问题描述
【题目描述】
【输入格式】
【输出格式】
【样例输入】
【样例输出】
【样例解释】
【数据约定】
题目解析
暴力法
循环每一轮攻击,当生命值为负数时输出当前攻击轮数并返回。
这道题采用暴力法可以通过70%的数据。
差分数组法
简单举个例子:
若一个数组d初始状态为[8,1,3,6,5,4,2];
- [3-5] +2(第三个数到第五个数均+2)
若给定差分数组c = [0,0,2,0,0,-2,0,0]以及差分数组的前缀和 s = [0,0,2,2,2,0,0]则可以很容易发现三者的关系:
d [ ] + s [ ] = 本 轮 最 终 状 态 d[]+s[]=本轮最终状态 d[]+s[]=本轮最终状态
因此在遭受本次攻击之后d = [8,1,5,8,7,4,2] - [1-5] -2(第一个数到第五个数均 -2)
此时c = [-2,0,0,0,2,0,0],s = [-2,-2,-2,-2,-2,0,0]
因此在遭受本次攻击之后d = [6,-1,1,4,3,4,2]。
在考场中我们如果想不到这种解法,暴力解题也是性价比最高的。
C++代码
#include<bits/stdc++.h>
using namespace std;
int A,B,C,m,a,b,c;
int getInt() //快速输入
{
char ch = getchar();
int x=0,f=1;
while(ch<'0'||ch>'9')
{
if(ch=='-')
{
f = -1;
ch = getchar();
}
}
while(ch>='0'&&ch<='9')
{
x = x*10+ch-'0';
ch = getchar();
}
return x*f;
}
inline int getIndex(int x,int y,int z)
{
return ((x-1)*b+(y-1))*c+z;
}
int main()
{
A = getInt();
B = getInt();
C = getInt();
m = getInt();
a = A+1; b = B+1; c = C+1;
int *data = new int[a*b*c];
int (*atk)[7] = new int [m+1][7];
for(int i=1;i<=A;i++)
for(int j=1;j<=B;j++)
for(int k=1;k<=C;k++)
data[getIndex(i,j,k)] = getInt();
for(int i=1;i<=m;i++)
{
for(int j=0;j<7;j++)
atk[i][j] = getInt();
for(int x=atk[i][0];x<=atk[i][1];x++) //层的范围
{
for(int y=atk[i][2];y<=atk[i][3];y++) //行的范围
{
for(int z=atk[i][4];z<=atk[i][5];z++) //列的范围
{
data[getIndex(x,y,z)]-=atk[i][6];
if(data[getIndex(x,y,z)]<0)
{
cout<<i<<endl;
delete []data;
delete []atk;
return 0;
}
}
}
}
}
}