题目描述有一条很长的队伍,队伍里面一共有n个人。所有的人分为三类:警察,小偷和普通人。将队伍里面的人从前到后由1到n编号,编号为i的人与编号为j的人的距离为i与j之差的绝对值。
每一个警察有一个能力值x,表示他能够监视与他距离不超过x的所有人,小偷被警察发现当且仅当他被一个或多个警察监视到。你知道在整条队伍中,一共有多少个小偷会被警察发现吗?
输入
输入有两行,第一行一个数n(1<=n<=100000),接下来一行有一个长度为n的字符串,依次表示队伍中的每一个人。如果某一位是1-9的某个数字x,表示这一位是一个能力值为x的警察;如果某一位是字符X表示这一位是小偷;如果某一位是字符#表示这是一个普通人。输入保证不会出现其它字符。
|
样例输入
9 X1X#2X#XX
|
输出
输出一个数,整条队伍中被警察发现的小偷总数。
|
样例输出
3 |
思路在代码中给出。
package JD;
import java.util.Scanner;
public class duilie {
public static void main(String[] rags) {
Scanner sc = new Scanner(System.in);
while (sc.hasNext()) {
int n = sc.nextInt();
String str = sc.next();
System.out.println(findTheif(str));
}
}
/*
* 简单思路:当发现一个警察时,就将他监视范围内的小偷抓出来,并将小偷替换成普通人,继续向后遍历寻找警察
*/
public static int findThrif(String str) {
char[] ch = str.toCharArray();
int count = 0;
int len = ch.length;
for (int i = 0; i < len; i++) {
if (ch[i] - '0' >= 0 && ch[i] - '0' <= 9) {
for (int j = i; j < len && j <= i + (ch[i] - '0'); j++) {
if (ch[j] == 'X') {
count++;
ch[j] = '#';
}
}
for (int j = i; j >= 0 && j >= i - (ch[i] - '0'); j--) {
if (ch[j] == 'X') {
count++;
ch[j] = '#';
}
}
}
}
return count;
}
//方法二:
//分别记录小偷在队列中出现的位置(T[i] = j,表示第i个小偷在队列中的位置为j),
//以及警察所能监视的区域(P[k-n]~P[k+n] == 1即所监视区域全为1),然后判断P[T[i]] ==1,
//如果为1,该位置上的小偷会被抓住,
public static int findTheif(String str) {
int count = 0;
if (str == null)
return count;
char[] ch = str.toCharArray();
int n = ch.length;
int[] T = new int[n + 1];
int[] P = new int[n];
int m = 1;
for (int i = 0; i < n; i++) {
if (ch[i] == 'X') {
T[m++] = i;
} else {
T[m++] = -1;
}
}
for (int i = 0; i < n; i++) {
if ((ch[i] - '0') >= 0 && (ch[i] - '0') <= 9) {
for (int j = i + 1; j < n && j <= i + (ch[i] - '0'); j++) {
P[j] = 1;
}
for (int j = i - 1; j >= 0 && j >= (i - (ch[i] - '0')); j--) {
P[j] = 1;
}
}
}
int k = 1;
while (k < T.length) {
if (T[k] != -1) {
if (P[T[k]] == 1) {
count++;
}
}
k++;
}
return count;
}
}