扫描透镜

Jun 23, 2016


题目来源:网易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;
    } 
}

上一篇博客:排序算法的稳定性
下一篇博客:java8 lambda & effectively final