Сортировка двоичной 2D матрицы?

Я использую этот код. Это - код VB, но можно легко перевести его в C#. Это работает

Function NumberToText(ByVal n As Integer) As String

   Select Case n
Case 0
  Return ""

Case 1 To 19
  Dim arr() As String = {"One","Two","Three","Four","Five","Six","Seven", _
    "Eight","Nine","Ten","Eleven","Twelve","Thirteen","Fourteen", _
      "Fifteen","Sixteen","Seventeen","Eighteen","Nineteen"}
  Return arr(n-1) & " "

Case 20 to 99
  Dim arr() as String = {"Twenty","Thirty","Forty","Fifty","Sixty","Seventy","Eighty","Ninety"}
  Return arr(n\10 -2) & " " & NumberToText(n Mod 10)

Case 100 to 199
  Return "One Hundred " & NumberToText(n Mod 100)

Case 200 to 999
  Return NumberToText(n\100) & "Hundreds " & NumberToText(n mod 100)

Case 1000 to 1999
  Return "One Thousand " & NumberToText(n Mod 1000)

Case 2000 to 999999
  Return NumberToText(n\1000) & "Thousands " & NumberToText(n Mod 1000)

Case 1000000 to 1999999
  Return "One Million " & NumberToText(n Mod 1000000)

Case 1000000 to 999999999
  Return NumberToText(n\1000000) & "Millions " & NumberToText(n Mod 1000000)

Case 1000000000 to 1999999999
  Return "One Billion " & NumberTotext(n Mod 1000000000)

Case Else
  Return NumberToText(n\1000000000) & "Billion " _
    & NumberToText(n mod 1000000000)
End Select
End Function

, Вот код в c#

public static string AmountInWords(double amount)
{
        var n = (int)amount;

        if (n == 0)
            return "";
        else if (n > 0 && n <= 19)
        {
            var arr = new string[] { "One", "Two", "Three", "Four", "Five", "Six", "Seven", "Eight", "Nine", "Ten", "Eleven", "Twelve", "Thirteen", "Fourteen", "Fifteen", "Sixteen", "Seventeen", "Eighteen", "Nineteen" };
            return arr[n - 1] + " ";
        }
        else if (n >= 20 && n <= 99)
        {
            var arr = new string[] { "Twenty", "Thirty", "Forty", "Fifty", "Sixty", "Seventy", "Eighty", "Ninety" };
            return arr[n / 10 - 2] + " " + AmountInWords(n % 10);
        }
        else if (n >= 100 && n <= 199)
        {
            return "One Hundred " + AmountInWords(n % 100);
        }
        else if (n >= 200 && n <= 999)
        {
            return AmountInWords(n / 100) + "Hundred " + AmountInWords(n % 100);
        }
        else if (n >= 1000 && n <= 1999)
        {
            return "One Thousand " + AmountInWords(n % 1000);
        }
        else if (n >= 2000 && n <= 999999)
        {
            return AmountInWords(n / 1000) + "Thousand " + AmountInWords(n % 1000);
        }
        else if (n >= 1000000 && n <= 1999999)
        {
            return "One Million " + AmountInWords(n % 1000000);
        }
        else if (n >= 1000000 && n <= 999999999)
        {
            return AmountInWords(n / 1000000) + "Million " + AmountInWords(n % 1000000);
        }
        else if (n >= 1000000000 && n <= 1999999999)
        {
            return "One Billion " + AmountInWords(n % 1000000000);
        }
        else
        {
            return AmountInWords(n / 1000000000) + "Billion " + AmountInWords(n % 1000000000);
        }
    }
6
задан Tom 23 November 2009 в 05:23
поделиться

5 ответов

Алгоритм, основанный на моделировании отжига , может справиться с подобными вещами без особых проблем. Не очень хорошо, если у вас есть маленькие матрицы, которые, скорее всего, имеют фиксированное решение, но отлично, если ваши матрицы становятся больше и проблема становится сложнее.

(Тем не менее, ваше желание, чтобы вставки можно было выполнять поэтапно, также не оправдано.)

Предварительные сведения

  1. Разработайте функцию производительности, которая «оценивает» матрицу - матрицы, которые ближе к вашей треугольности, должны получить более высокую оценку, чем те, которые меньше треугольника-y.

  2. Разработайте набор операций, которые разрешены в матрице. Ваше описание было немного двусмысленным, но если вы можете поменять местами строки, тогда одна операция будет SwapRows (a, b) . Другой может быть SwapCols (a, b) .

Петля отжига

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

Решение о фиксации преобразования - это самое интересное: вам нужно решить, выполнять эту операцию или нет. Ближе к концу процесса отжига вы принимаете только преобразования, улучшающие оценку матрицы. Но раньше, в более хаотичное время, вы допускаете преобразования, которые не улучшают счет. Вначале алгоритм "горячий" и все идет. В конце концов, алгоритм остывает, и разрешаются только хорошие преобразования. Если вы линейно охладите алгоритм, тогда выбор, принимать ли преобразование, будет следующим:

public bool ShouldAccept(double cost, double temperature, Random random) {
    return Math.Exp(-cost / temperature) > random.NextDouble();
}

Вы должны прочитать отличную информацию, содержащуюся в Числовые рецепты для получения дополнительной информации об этом алгоритме.

Короче говоря. , вам следует изучить некоторые из этих алгоритмов общего назначения. Это позволит вам решать большие классы задач, которые сложно решить аналитически.

Алгоритм подсчета очков

Это, вероятно, самая сложная часть. Вам нужно будет придумать счетчик, который будет направлять процесс отжига к вашей цели. Счетчик должен быть непрерывной функцией, которая дает большие числа по мере приближения матрицы к идеальному решению.

Как вы измеряете «идеальное решение» - треугольность? Вот наивный и легкий бомбардир: Для каждой точки вы знаете, должно ли она быть 1 или 0 . Добавьте +1 к результату, если матрица верна, -1, если она неверна. Вот код, чтобы я мог быть явным (не тестировался! Пожалуйста, просмотрите!)

int Score(Matrix m) {
    var score = 0;
    for (var r = 0; r < m.NumRows; r++) {
        for (var c = 0; c < m.NumCols; c++) {
            var val = m.At(r, c);
            var shouldBe = (c >= r) ? 1 : 0;
            if (val == shouldBe) {
                score++;
            }
            else {
                score--;
            }
        }
    }
    return score;
} 

С этим алгоритмом подсчета очков случайное поле из единиц и нулей даст оценку 0. «Противоположный» треугольник даст наиболее отрицательную оценку, и правильное решение даст наиболее положительную оценку. Оценка двух оценок даст вам стоимость.

Если этот счетчик не работает для вас, вам нужно будет «настроить» его, пока он не создаст нужные вам матрицы.

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

6
ответ дан 10 December 2019 в 02:49
поделиться

Основной алгоритм:

  1. Определить суммы строк и сохранить ценности. Определите суммы столбцов и сохранить значения.
  2. Сортировать суммы строк в порядке возрастания. Сортировать столбец суммы в порядке возрастания.

Надеюсь, у вас должна получиться матрица с максимально близкой к правому верхнему треугольному участку.

0
ответ дан 10 December 2019 в 02:49
поделиться

Вот отправная точка:

Преобразование каждой строки из двоичных разрядов в число

Сортировка чисел в порядке убывания.

Затем преобразование каждой строки обратно в двоичное.

0
ответ дан 10 December 2019 в 02:49
поделиться

Я придумал приведенный ниже алгоритм, и он, кажется, работает правильно.

Этап 1: перемещение строк с наибольшим количеством 1 вверх и столбцов с крайний 1 справа.

  1. Первые ряды. Отсортируйте строки, посчитав их 1 сек. Нам все равно если 2 строки имеют одинаковое количество 1 s.
  2. Теперь столбцы. Сортировать столбцы по считая их 1 с. Нам все равно если 2 столбца имеют одинаковое количество 1 сек.

Фаза 2: повторение фазы 1 , но с дополнительными критериями, так что мы удовлетворяем морфу треугольной матрицы.
Критерий для строк: если 2 строки имеют одинаковое количество 1 секунд, мы перемещаем вверх строку, которая начинается с меньшего количества 0 секунд.

Критерий для столбцов: если 2 столбца имеют одинаковое количество 1 с, мы перемещаем вправо столбец, в нижней части которого меньше 0 с.


Пример:

Фаза 1

  1 2 3 4                     1 2 3 4                   4 1 3 2
A 0 1 1 0                   B 1 1 1 0                 B 0 1 1 1
B 1 1 1 0  - sort rows->    A 0 1 1 0  - sort cols->  A 0 0 1 1
C 0 1 0 0                   D 1 1 0 0                 D 0 1 0 1
D 1 1 0 0                   C 0 1 0 0                 C 0 0 0 1

Фаза 2

  4 1 3 2                     4 1 3 2
B 0 1 1 1                   B 0 1 1 1
A 0 0 1 1  - sort rows->    D 0 1 0 1  - sort cols-> "completed"
D 0 1 0 1                   A 0 0 1 1
C 0 0 0 1                   C 0 0 0 1

Редактировать: оказывается, что мой алгоритм не всегда дает правильные треугольные матрицы.
Например:

Этап 1

   1 2 3 4                    1 2 3 4                
A  1 0 0 0                  B 0 1 1 1                
B  0 1 1 1 - sort rows->    C 0 0 1 1  - sort cols-> "completed"
C  0 0 1 1                  A 1 0 0 0                
D  0 0 0 1                  D 0 0 0 1                

Этап 2

   1 2 3 4                    1 2 3 4                   2 1 3 4
B  0 1 1 1                  B 0 1 1 1                 B 1 0 1 1
C  0 0 1 1 - sort rows->    C 0 0 1 1  - sort cols->  C 0 0 1 1
A  1 0 0 0                  A 1 0 0 0                 A 0 1 0 0
D  0 0 0 1                  D 0 0 0 1                 D 0 0 0 1
                           (no change)

(*) Возможно, этап 3 увеличит хорошие результаты. На этом этапе мы размещаем строки, которые начинаются с меньшего количества 0 в верхней части.

2
ответ дан 10 December 2019 в 02:49
поделиться

Обрабатывать строки как двоичные числа, причем крайний левый столбец является самым старшим битом, и сортировать их в порядке убывания, сверху вниз

Обрабатывать столбцы как двоичные числа с самой нижней строкой как самый старший бит и отсортируйте их в порядке возрастания слева направо.

Повторяйте, пока не достигнете фиксированной точки. Доказательство того, что алгоритм завершается, оставлено в качестве упражнения для читателя.

0
ответ дан 10 December 2019 в 02:49
поделиться
Другие вопросы по тегам:

Похожие вопросы: