Как применить матрицу преобразования?

Проблема в том, что в строке 32, 33 вместо массива 'weight' есть индексная переменная 'w'. И еще одна вещь, если вы используете 'j' для индексации, чем объявляете ее 'int', а не float.

Я не уверен, что ваш алгоритм будет работать. Но это будет работать сейчас. Если вам нужна помощь в algo, вы можете прокомментировать.

 //maximum value of loot
#include<iostream>
#include<vector>
#include<algorithm>
using namespace std;

int maxi(int a , int b)
{
    if(a>b) return a;
    else return b;
}

int main()
{
    int n,W,V=0,j;// line i have changed
    float v,w;
    vector<int> values;
    vector<int> weights;
    vector<float> vbyw;
    cin>>n>>W;
    for(int i = 0 ; i<n; i++)
    {
        cin>>v>>w;
        values.push_back(v);
        weights.push_back(w);
        vbyw.push_back(float(v/w));
    }
    sort(vbyw.begin(),vbyw.end());
    j = vbyw.size()-1;
    while(W>0 && j>0)
    {
        W = W - maxi(weights[j],W); // line i have changed
        V = V + maxi(weights[j],W)*vbyw[j]; // line i have changed
        j--;
    }
    cout<<V;
    return 0;
}
12
задан 11 May 2009 в 21:30
поделиться

3 ответа

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

Умножение матриц

Перво-наперво. Умножение матриц - это достаточно простое дело .

Допустим, у вас есть матрицы A , B и C , где ] AB = C . Допустим, вы хотите вычислить значение матрицы C в строке 3, столбце 2.

  • Возьмите третью строку A и второй столбец B . Теперь у вас должно быть такое же количество значений из A и B . (Если вы этого не сделаете, умножение матриц не определено для этих двух матриц. Вы не можете этого сделать.) Если обе являются матрицами 4 × 4, у вас должно быть 4 значения из A (строка 3) и 4 значения из B (столбец 2).
  • Умножьте каждое значение A на каждое значение B . У вас должно получиться 4 новых значения.
  • Сложите эти значения.

Теперь у вас есть значение матрицы C в строке 3, столбце 2. Задача, конечно же, состоит в том, чтобы сделать это. программно.

/* AB = C

Row-major ordering
a[0][0] a[0][2] a[0][3]...
a[1][0] a[1][4] ...
a[2][0] ...
...*/
public static mmMul(double[][] a, double[][] b, double[][] c) {
    c_height = b.length; // Height of b
    c_width = a[0].length; // Width of a
    common_side = a.length; // Height of a, width of b

    for (int i = 0; i < c_height; i++) {
        for (int j = 0; j < c_width; j++) {
            // Ready to calculate value of c[i][j]
            c[i][j] = 0;

            // Iterate through ith row of a, jth col of b in lockstep
            for (int k = 0; k < common_side; k++) {
                c[i][j] += a[i][k] * b[k][j];
            }
        }
    }
}

Однородные координаты

У вас есть трехмерные координаты. Допустим, у вас есть (5, 2, 1). Это декартовы координаты. Назовем их ( x , y , z ).

Однородные координаты означают, что вы пишете лишнюю 1 в конце декартовых координат. (5, 2, 1) становится (5, 2, 1, 1). Назовем их ( x , y , z , w ).

Всякий раз, когда вы выполняете преобразование, которое делает w ≠ 1, вы разделите каждый компонент ваших координат на w . Это изменяет ваши x , y и z , и снова делает w = 1. (В этом нет ничего плохого, даже если ваше преобразование не меняет w . Оно просто делит все на 1, что ничего не делает.)

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


Преобразование точки

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

Я также начну с предположения, что ваши матрицы крена, наклона и панорамирования верны.

Когда вы хотите преобразовать точку с помощью матрицы преобразования, вы умножаете эту матрицу справа на вектор-столбец, представляющий вашу точку , Допустим, вы хотите перевести (5, 2, 1) некоторой матрицей преобразования A . Сначала вы определяете v = [5, 2, 1, 1] T . (Я пишу [ x , y , z , w ] T с маленьким T означает, что вы должны записать его как вектор-столбец.)

// Your point in 3D
double v[4][5] = {{5}, {2}, {1}, {1}}

В этом случае, Av = v 1 , где v 1 - ваша преобразованная точка. Выполните это умножение как матричное умножение, где A равно 4 × 4, а v равно 4 × 1. В итоге вы получите матрицу 4 × 1 (которая является еще одним вектором-столбцом).

// Transforming a single point with a roll
double v_1[4][6];
mmMul(rollMat, v, v_1);

Теперь, если вам нужно применить несколько матриц преобразования, сначала объедините их в одну матрицу преобразования. Сделайте это путем умножения матриц вместе в том порядке, в котором вы хотите, чтобы они применялись.

Программно вы должны начать с единичной матрицы и умножить каждую матрицу преобразования вправо. Пусть I 4 будет единичной матрицей 4 × 4, и пусть A 1 , A 2 , A 3 , ... ваши матрицы преобразования. Пусть ваша окончательная матрица преобразования будет A final

A final I 4
A final A финал A 1
A финал A финал A 2
A финал A final A 3

Обратите внимание, что я использую эту стрелку для обозначения присваивания. Когда вы реализуете это, убедитесь, что не перезаписали A final , пока вы все еще используете его в вычислении матричного умножения! Сделайте копию.

// A composite transformation matrix (roll, then tilt)

double a_final[4][4] =
{
    {1, 0, 0, 0},
    {0, 1, 0, 0},
    {0, 0, 1, 0},
    {0, 0, 0, 1}
}; // the 4 x 4 identity matrix

double a_final_copy[4][4];
mCopy(a_final, a_final_copy); // make a copy of a_final
mmMul(rollMat, a_final_copy, a_final);
mCopy(a_final, a_final_copy); // update the copy
mmMul(tiltMat, a_final_copy, a_final);

Наконец, проделайте то же умножение, что и выше: A final v = v 1

// Use the above matrix to transform v
mmMul(a_final, v, v_1);

От начала до конца

Трансформации камеры должны быть представлены в виде матрицы просмотра. Выполните здесь операцию A view v = v 1 . ( v представляет координаты вашего мира в виде вектора-столбца 4 × 1, A final - это ваше A представление .)

// World coordinates to eye coordinates
// A_view is a_final from above
mmMult(a_view, v_world, v_view);

Проекция преобразования описывают перспективное преобразование. Это то, что делает более близкие объекты больше, а далекие - меньше. Это выполняется после преобразования камеры. Если вам еще не нужна перспектива, просто используйте матрицу идентичности для матрицы проекции. В любом случае, выполните здесь A v 1 = v 2 .

// Eye coordinates to clip coordinates
// If you don't care about perspective, SKIP THIS STEP
mmMult(a_projection, v_view, v_eye);

Затем вам нужно выполнить перспективное деление. Это углубляется в однородные координаты, которые я еще не описал. В любом случае разделите каждый компонент v 2 на последний компонент v 2 . Если v 2 = [ x , y , z , w ] T , затем разделите каждый компонент на w (включая сам w ). У вас должно получиться w = 1. (Если ваша матрица проекции является единичной матрицей, как я описал ранее, этот шаг ничего не должен делать.)

// Clip coordinates to normalized device coordinates
// If you skipped the previous step, SKIP THIS STEP
for (int i = 0; i < 4; i++) {
    v_ndc[i] = v_eye[i] / v[3];
}

Наконец, возьмите v ] 2 . Первые две координаты - это ваши координаты x и y . Третий - z , который можно выбросить. (Позже, когда вы станете очень продвинутыми, вы можете использовать это значение z , чтобы выяснить, какая точка находится впереди или позади какой-либо другой точки.) И на этом этапе последний компонент - w = 1, поэтому вам это больше не нужно.

x = v_ndc[0]
y = v_ndc[1]
z = v_ndc[2]  // unused; your screen is 2D

Если вы пропустили этапы разделения перспективы и перспективы, используйте v_view вместо v_ndc выше.

Это очень похоже на набор систем координат OpenGL . Разница в том, что вы начинаете с мировых координат, а OpenGL начинается с координат объекта. Разница в следующем:

  • Вы начинаете с мировых координат.
    • OpenGL начинается с координат объекта.
  • Вы используете матрицу представления для преобразования мировых координат в координаты глаз
    • OpenGL использует матрицу ModelView для преобразования координат объекта в координаты глаза

С этого момента все остается прежним.

28
ответ дан 2 December 2019 в 04:43
поделиться

Объем этого слишком велик, чтобы получить здесь хороший ответ: я бы порекомендовал прочитать хорошую ссылку по теме. Мне всегда нравились Фоли и ВанДэм ...

3
ответ дан 2 December 2019 в 04:43
поделиться
Другие вопросы по тегам:

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