思路简述
二维差分+矩阵旋转
思路详述
1.二维差分,对于每一个标签而言,有对一维的影响和二维的传递之分
2.为什么要差分?对于每一个目标而言,它对以其为左上角顶点,k为边长的三角形内的点都有一个贡献,这种范围内的累加就考虑用前缀和(这里是二维差分)
3.为什么要矩阵旋转?由于在某个点喷的方向不同,得到的值也不同。所以每个目标的贡献只能对一个方向
4.好烦啊,怎么用文字表述呢
\(Code\)
#include<bits/stdc++.h>
using namespace std;
int n,m,k;
string s[100005];
int ss1()
{
vector<vector<int> > a(n+5,vector<int> (m+5));//二维数组n*m
vector<vector<int> > b(n+5,vector<int> (m+5));
for(int i=1;i<=n;i++)
{
for(int j=1;j<=m;j++)
{
if(s[i][j]=='#')
{
a[i][j]++;
if(i+k<n)
{
a[i+k+1][j]--;//传递截至点
b[i+k+1][j]++;
}
if(j+k<m) b[i][j+k+1]--;//b代表斜线传递
else if(i+j+k-m+1<=n) b[i+j+k-m+1][m]--;//三角形的范围可能超过了矩阵范围
}
}
}
int ans=0;
for(int i=1;i<=n;i++)
{
int sum=0;
for(int j=1;j<=m;j++)
{
sum+=a[i][j]+b[i][j];//赋能
ans=max(ans,sum);
a[i+1][j]+=a[i][j];//传递
b[i+1][j-1]+=b[i][j];
}
}
return ans;
}
void rotate90Degrees()
{
vector<string> temp(m+1);//二维字符串,string是一维,vector是一维,m+1代表vector的大小,即含有几个string
for (int j = 1; j <= m; ++j) temp[j].resize(n+1, ' ');//把temp中的每一个元素(string)变成长度为n+1的空格
for (int i = 1; i <= n; ++i)
for (int j = 1; j <= m; ++j)
temp[j][n-i+1] = s[i][j];//旋转,注意这里不能temp[i][j]=s[j][n-i+1],因为s会越界
for (int i = 1; i <= m; i++) s[i] = temp[i];//字符串的复制可以直接等于
}
int main()
{
ios::sync_with_stdio(false);
cin.tie(0);
cout.tie(0);
int t;
cin>>t;
while(t--)
{
cin>>n>>m>>k;
for(int i=1;i<=n;i++)
{
cin>>s[i];
s[i]=" "+s[i];//使下标从1开始
}
int ans=0;
for(int i=1;i<=4;i++)
{
ans=max(ans,ss1());
rotate90Degrees();
swap(n,m);//旋转后的矩阵nm发生变换
}
cout<<ans<<endl;
}
return 0;
}
标签:string,int,Shooter,差分,二维,vector,Mischievous,一维
From: https://www.cnblogs.com/pure4knowledge/p/17987948