原文链接:华为od机试 图像物体的边界 - 知乎
解题思路
知乎上用的是并查集,我这边用的是循环队列。 找边界就是找任何两个5之间的距离,通过观察发现两个5之间距离只要满足绝对值: x1-x2<=3 或者 y1-y2<=3就会出现边界相交。既如此,那就遍历计算每个5与剩下5之间的坐标距离,查找过程用到了队列,因为A与B本不相交,但A与C,B与C相交就会导致A-B相交,所以用队列可以把这种乱七八糟的关系给串起来
public static void main(String[] args) {
Scanner sc = new Scanner(System.in);
while(sc.hasNext()) {
int row =sc.nextInt();
int col = sc.nextInt();
int[][] nums = new int[row][col];
// 将5所在坐标放入一个数组中,供后续计算
List<Integer[]> fiveAddrList = new ArrayList<Integer[]>();
for(int i=0; i< row;i++) {
for(int j=0;j < col; j++) {
nums[i][j] = sc.nextInt();
if(nums[i][j] == 5) {
Integer[] fiveAddr = {i,j};
fiveAddrList.add(fiveAddr);
}
}
}
int count =0;
Map<Integer,Integer> historyVisMap = new HashMap<Integer, Integer>();
for(int i=0; i< fiveAddrList.size();i++) {
if(historyVisMap.get(i) == null) {// null:not used
Deque<Integer[]> que = new LinkedList<Integer[]>();
que.addLast(fiveAddrList.get(i));
count +=1; // count increase 1
historyVisMap.put(i, 1); // mark used
while(!que.isEmpty()) {
Integer[] addr = que.pollFirst();
for(int j=0; j< fiveAddrList.size(); j++) {
if(historyVisMap.get(j) == null
&& (Math.abs(fiveAddrList.get(j)[0] - addr[0]) <= 3
|| Math.abs(fiveAddrList.get(j)[1] - addr[1]) <= 3)) {
historyVisMap.put(j, 1); // mark used
que.addLast(fiveAddrList.get(j));
}
}
}
}
}
System.out.println(count);
}
}