CF2113C Smilo and Minecraft
题目链接: https://codeforces.com/problemset/problem/2113/C
题意:
给定一个 的区域,某些位置有金块,每次可以在空格子放置一个 TNT,炸掉以 TNT 为中心、边长 的正方形区域中的所有物品,并获得位于正方形边界上的所有金块,求可以收集到金块的最大值。
思路:
假如我们把第一个爆炸点选在 ,这周围的金子就被炸没了,之后我们在这片区域四周选择新的爆炸点就不会让其他的金子消失。
所以可以枚举第一个爆炸点选取的位置所炸掉的金子个数。用所有金子的数量减去,来达到最大值。可以使用二维前缀和进行优化。
代码:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50
| #include <bits/stdc++.h> using namespace std; #define IOS ios::sync_with_stdio(0),cin.tie(0),cout.tie(0); const int N=505; char a[N][N]; int s[N][N]; void solve() { int n,m,k; cin>>n>>m>>k; k--; int sum=0; for(int i=1;i<=n;i++) { for(int j=1;j<=m;j++) { cin>>a[i][j]; s[i][j]=s[i-1][j]+s[i][j-1]-s[i-1][j-1]; if(a[i][j]=='g'){s[i][j]++;sum++;} } } int ans=0x3f3f3f3f; for(int i=1;i<=n;i++) { for(int j=1;j<=m;j++) { if(a[i][j]=='.') { int l=max(1,j-k); int r=min(m,j+k); int u=max(1,i-k); int b=min(n,i+k); ans=min(ans,s[b][r]-s[u-1][r]-s[b][l-1]+s[u-1][l-1]); } } } cout<<sum-ans<<endl; } signed main() { IOS int t; cin>>t; while(t--) { solve(); }
}
|