题目来源:网易2016研发工程师编程题
题目描述
在N*
M的草地上,提莫种了K个蘑菇,蘑菇爆炸的威力极大,兰博不想贸然去闯,而且蘑菇是隐形的.只 有一种叫做扫描透镜的物品可以扫描出隐形的蘑菇,于是他回了一趟战争学院,买了2个扫描透镜,一个 扫描透镜可以扫描出(3*
3)方格中所有的蘑菇,然后兰博就可以清理掉一些隐形的蘑菇. 问:兰博最多可以清理多少个蘑菇?
注意:每个方格被扫描一次只能清除掉一个蘑菇
。
解题思路
- 第一想法是使用暴力解法,穷举所有的扫描情况,记录最大值。这样子思想简单,但复杂度过高。
- 更好的解法是贪心法:第一次扫描时选最多的清除,紧接着第二次扫描也选择做多的清除,两次清除的总数就是答案。
代码实现
import java.util.Scanner;
/**
* 高效且简洁的解法
* 贪心法:第一次扫描,记录最多能扫描的最多的蘑菇数,然后清除;第二次同样记录能扫描的最多的蘑菇数,清除;两次清除之和即为最多清除的。
* @author chwl
* @Date 2016年5月30日 下午9:33:48
*/
public class Main {
public static void main(String[] args) {
Scanner in = new Scanner(System.in);
while(in.hasNext()){
int n = in.nextInt();
int m = in.nextInt();
int k = in.nextInt();
int[][] nums = new int[n+4][m+4];//外面包裹两层0,防止遍历时出界
for(int i=0;i<k;i++){
nums[in.nextInt()+1][in.nextInt()+1]++;
}
int[] direction = new int[]{-1,0,1};
System.out.println(getMax(nums,direction,n,m)+
getMax(nums,direction,n,m));
}
}
private static int getMax(int[][] nums, int[] direction,int n,int m) {
int max=-1;
int x=0,y=0;
for(int i=1;i<=n+2;i++){
for(int j=1;j<m+2;j++){
int sum =0;
for(int a=0;a<3;a++){//从九宫格中心从四周扩展
for(int b=0;b<3;b++){
if(nums[i+direction[a]][j+direction[b]]>0){
sum++;
}
}
}
if(sum>max){
max= sum;
x=i;
y=j;
}
}
}
for(int a=0;a<3;a++){
for(int b=0;b<3;b++){
if(nums[x+direction[a]][y+direction[b]]>0){
nums[x+direction[a]][y+direction[b]]--;
}
}
}
return max;
}
}