Полицейский-хакер и проблема воров - PullRequest
0 голосов
/ 30 мая 2020

Я пытаюсь решить проблему Policeman and Theives на сайте Hackeearth. Я могу уменьшить временную сложность, но три тестовых примера не работают. Похоже, в решении есть ошибка, которая вызывает небольшое несоответствие. Я неделями пытаюсь найти ошибку. Ниже приведены описание проблемы и мой код

Описание задачи «Полицейский и воры»:

Вам предоставляется сетка размеров, которая имеет следующие характеристики:

  • Каждая ячейка в сетке содержит либо полицейского, либо вора.
  • Полицейский может поймать вора, только если они оба находятся в одном ряду.
  • Каждый полицейский может поймать вора. поймать только одного вора.
  • Полицейский не может поймать вора, который находится на расстоянии более K единиц от полицейского. Напишите программу, чтобы найти максимальное количество воров, которые могут быть пойманы в сетке.

Формат ввода

  • Первая строка: T (количество тестовых примеров)

    Для каждого тестового примера

    • Первая строка содержит два целых числа, разделенных пробелами N и K
    • Следующие N строк содержат N символы, разделенные пробелами (обозначающие каждую ячейку в сетке)

Формат вывода

Для каждого тестового примера выведите максимальное число воров, которых можно поймать в сетке.

Мой код:

import java.io.*;
import java.util.*;

public class TestClass {
    public static void main(String[] args) throws IOException {
        BufferedReader br = new BufferedReader(new InputStreamReader(System.in));
        PrintWriter wr = new PrintWriter(System.out);
        int T = Integer.parseInt(br.readLine().trim());
        for(int t_i=0; t_i<T; t_i++)
        {
            String[] line = br.readLine().split(" ");
            int N = Integer.parseInt(line[0]);
            int K = Integer.parseInt(line[1]);
            char[][] A = new char[N][N];
            for(int i_A=0; i_A<N; i_A++)
            {
                String[] arr_A = br.readLine().split(" ");
                for(int j_A=0; j_A<arr_A.length; j_A++)
                {
                    A[i_A][j_A] = arr_A[j_A].charAt(0);
                }
            }

            int out_ = solution(A, K);
            System.out.println(out_);
            System.out.println("");
        }

        wr.close();
        br.close();
    }
    static int solution(char[][] A, int K){
        int count = 0;
        for(int i=0;i<A.length;i++){
            for(int j=0;j<A[i].length;j++){
                if(A[i][j]=='P'){
                    boolean thiefCaptured = false;
                    int x;
                    if(j-K >0){
                        x = j-K;
                    }else {
                        x = 0;
                    }
                    for(;x<j;x++) {
                        if (A[i][x] == 'T') {
                            A[i][x] = 'X';
                            A[i][j] = 'X';
                            count++;
                            thiefCaptured = true;
                            break;
                        }
                    }
                    int y;
                    if(j+K < A[i].length){
                        y = j+K;
                    }else{
                        y = A[i].length - 1;
                    }
                    for(;(y>j) && (thiefCaptured == false);y--){
                        if(A[i][y]=='T'){
                            A[i][y] = 'X';
                            A[i][j] = 'X';
                            count++;
                            break;
                        }
                    }
                }
            }
        }
        return count;
    }
}

My Logi c Если элемент считается в качестве центра нашего поиска я сначала ищу воров из крайнего левого угла (на k единиц) и повторяю путь к центру. Если вор не найден, то я ищу вора из крайнего правого угла (на k единиц) по направлению к центру.

Неудачный ввод тестового примера:

1
18 2
P P T T T P T P P T T P P P T P P T
P P P P T P P T P P T P P P T P T P
P P P T T T T T P P T P T P T T P T 
P P P P P P T P P P T T T P T T T P
P P T P P T P P P T T P P T P P P T
P T P P P P P P P P P P T T P T P P
T P T T T P P P P T P T T T T P T P
T T P T P P P P P P P T T T P T P P
P T T T T P T T P T P P P P T T P T
P T P P T T P P P P P T T P T P P P
P T P T T P T P T P T P P P P P P T
P T P P T P T P T P T P T T T P P P
T T P T P P P P P P T T T P T P T P
P T T P P P P P T P T P T P T P P T
P T P T T P T P T P P P P T P T P P
T P P P T P T P P P P P T T P P P P
P P T P P P P P P P P T T T P P T P
T T T P T P T P T P P T P P T P P P

Ожидаемый результат 113

Фактический выход 112

Вы можете помочь мне понять, в чем я ошибаюсь? На самом деле я пытаюсь найти решение в течение нескольких недель, но не могу добиться прогресса. Я знаю, что есть другое решение для того же вопроса. Но дело в том, что я хотел бы выяснить проблему или дыру в моем logi c. Пожалуйста, помогите мне.

Ссылка: Полицейские и воры на hackerearth

Ответы [ 3 ]

1 голос
/ 30 мая 2020

Ваша ошибка проявляется в строке i 11 (12-я строка, если считать естественно / на основе 1).

P T P P T P T P T P T P T T T P P P

В этой строке 8 воров. Их всех можно поймать. В следующей строке + обозначает полицейского или полицейского, успешно поймавшего вора, тогда как - означает того, кто его не поймает.

+ T - + T + T + T + T + T T T + + -

(Первый вор может быть пойман любым полицейский слева или справа, это не имеет значения для подсчета. Есть еще больше возможных вариантов того, кто поймает первых двух воров.)

Ваша программа «ловит» только 7 из 8 воров. . Перед этим рядом у вас есть счет 68, что я считаю правильным. После ряда ваш счет 75, он должен быть 76.

В ряду первые 5 воров пойманы должным образом. Что теперь делает полицейский с индексом 11? Вор слева уже пойман. Справа трое воров. Ваш второй самый внутренний l oop отсчитывается от y = j+K = 11 + 2 = 13, поэтому ловит вора с индексом 13, оставляя вора с индексом 12 непойманным. Следующий полицейский имеет индекс 15. Когда K равно 2, он / она не может поймать вора с индексом 12, расстояние слишком велико.

Изменить: моя идея решения. Поскольку вы опубликовали свое решение, я думаю, что могу опубликовать свое, ничего не испортив. Моя идея состоит в том, чтобы каждый вор обыскивал слева направо полицейского, который сможет поймать этого вора. Я начну поиск с того места, где остановился предыдущий поиск. Это гарантирует, что каждый полицейский поймает только одного вора.

    char[] row = { 'P', 'T', 'P', 'P', 'T', 'P', 'T', 'P', 'T',
            'P', 'T', 'P', 'T', 'T', 'T', 'P', 'P', 'P' };
    int k = 2; // The uppercase K from the problem

    int count = 0;
    // Index from where to search for the next police officer to catch a thief
    int pix = 0;
    for (int ix = 0; ix < row.length; ix++) {
        if (row[ix] == 'T') {
            if (pix < ix - k) {
                pix = ix - k;
            }
            int searchLimit = Math.min(row.length, ix + k + 1);
            while (pix < searchLimit && row[pix] != 'P') {
                pix++;
            }
            if (pix < searchLimit) { // Found
                count++;
                pix++;
            }
        }
    }

    System.out.println(count);

Вывод:

8

Я не использую никаких вспомогательных структур данных, и я не изменяю входной массив. Я считаю, что этот алгоритм эффективен (я не пробовал его на хакерской земле).

Проблема симметрична для полицейских и воров, поэтому можно сделать это и наоборот, для каждого полицейского, ищущего по адресу вор, чтобы поймать, он будет работать так же.

Если вызов Math.min() кажется необычным, вместо этого используйте тернарный оператор ? : или конструкцию if - else.

PS Может быть, на hackerearth было бы более уместно иметь P для полицейского и H для хакера и спрашивать, сколько хакеров сбежали, не будучи пойманными полицией. Шучу.

0 голосов
/ 31 мая 2020

Я получил решение с веб-сайта GeekForGeeks, в котором используется действительно простой лог c, основанный на индексе полиции и вора. Я подумал, что это так просто !!! ?? Ну так устроен мир. В любом случае, вот оптимальное решение для вышеуказанной проблемы,

import java.io.*;
import java.util.*;

public class TestClass {

    public static void main(String[] args) throws IOException {
        BufferedReader br = new BufferedReader(new InputStreamReader(System.in));
        PrintWriter wr = new PrintWriter(System.out);
        int T = Integer.parseInt(br.readLine().trim());
        for(int t_i=0; t_i<T; t_i++)
        {
            String[] line = br.readLine().split(" ");
            int N = Integer.parseInt(line[0]);
            int K = Integer.parseInt(line[1]);
            char[][] A = new char[N][N];
            for(int i_A=0; i_A<N; i_A++)
            {
                String[] arr_A = br.readLine().split(" ");
                for(int j_A=0; j_A<arr_A.length; j_A++)
                {
                    A[i_A][j_A] = arr_A[j_A].charAt(0);
                }
            }

            int out_ = solution(A, K);
            System.out.println(out_);
            System.out.println("");
        }

        wr.close();
        br.close();
    }
    static int solution(char[][] arr, int K){
        int count = 0;
        for(int i=0;i<arr.length;i++){
                ArrayList<Integer> thi = new ArrayList<>();
                ArrayList<Integer> pol = new ArrayList<>();
                for (int s = 0; s < arr[i].length; s++) {
                    if (arr[i][s] == 'P')
                        pol.add(s);
                    else if (arr[i][s] == 'T')
                        thi.add(s);
                }
                int l = 0, r = 0;
                while (l < thi.size() && r < pol.size()) {
                    if (Math.abs(thi.get(l) - pol.get(r)) <= K) {
                        count++;
                        l++;
                        r++;
                    }
                    else if (thi.get(l) < pol.get(r))
                        l++;
                    else
                        r++;
                }
        }
        return count;
    }
}

Ссылка: Полицейский и воры Компьютерщик для компьютерных фанатов

0 голосов
/ 30 мая 2020

Я добавил лог c, чтобы исправить ошибку, указанную @ OleV.V. Добавленный лог c равен: если два вора присутствуют последовательно в полиции, сначала поймайте ближайшего Теперь неудачные тестовые примеры проходят, но три из ранее пройденных тестовых случаев истекают по времени проблема сложности. Ниже приведен код после устранения ошибки, указанной @ OleV.V. Теперь нужно исправить это с точки зрения временной сложности: (

import java.io.*;
import java.util.*;

public class TestClass {
    public static void main(String[] args) throws IOException {
        BufferedReader br = new BufferedReader(new InputStreamReader(System.in));
        PrintWriter wr = new PrintWriter(System.out);
        int T = Integer.parseInt(br.readLine().trim());
        for(int t_i=0; t_i<T; t_i++)
        {
            String[] line = br.readLine().split(" ");
            int N = Integer.parseInt(line[0]);
            int K = Integer.parseInt(line[1]);
            char[][] A = new char[N][N];
            for(int i_A=0; i_A<N; i_A++)
            {
                String[] arr_A = br.readLine().split(" ");
                for(int j_A=0; j_A<arr_A.length; j_A++)
                {
                    A[i_A][j_A] = arr_A[j_A].charAt(0);
                }
            }

            int out_ = solution(A, K);
            System.out.println(out_);
            System.out.println("");
        }

        wr.close();
        br.close();
    }
    static int solution(char[][] A, int K){
        int count = 0;
        for(int i=0;i<A.length;i++){
            for(int j=0;j<A[i].length;j++){
                if(A[i][j]=='P'){
                    ArrayList<Integer> leftarr = new ArrayList<>();
                    ArrayList<Integer> rightarr = new ArrayList<>();
                    int x;
                    if(j-K >0){
                        x = j-K;
                    }else {
                        x = 0;
                    }
                    for(;x<j;x++) {
                        if (A[i][x] == 'T') {
                            leftarr.add(x);
                        }
                    }
                    if(leftarr.size() != 0){
                        Collections.sort(leftarr);
                        A[i][leftarr.get(0)] = 'X';
                        A[i][j] = 'X';
                        count++;
                        continue;
                    }
                    int y;
                    if(j+K < A[i].length){
                        y = j+K;
                    }else{
                        y = A[i].length - 1;
                    }
                    for(;y>j;y--){
                        if (A[i][y]=='T'){
                            rightarr.add(y);
                        }
                    }
                    if(rightarr.size()!=0){
                        Collections.sort(rightarr);
                        A[i][rightarr.get(0)] = 'X';
                        A[i][j] = 'X';
                        count++;
                    }
                }
            }
        }
        return count;
    }
}
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...