《C++程序设计》 Y.Daniel Liang 著 第八章习题答案

例8.1

·(按列求元素和)编写一个函数,返回一个矩阵特定列的所有元素和,函数头如下:
const int SIZE = 4;
double sumColumn ( const double m[ ][SIZE], int rowSize, int columnIndex );
编写一个测试程序,读入 3 × 4 3\times4 3×4 的矩阵,打印输出每一列的元素和。

#include<iostream>
using namespace std;

const int SIZE = 4;

double sumColumn(const double m[][SIZE], int rowSize, int columnIndex){
    double sum = 0;
    for (int i = 0; i < rowSize; i++)
        sum += m[i][columnIndex];

    return sum;
}

int main(){
    cout << "Enter a 3-by-4 matrix row by row:" << endl;
    double m[3][SIZE];
    for (int i = 0; i < 3; i++)
        for (int j = 0; j < SIZE; j++)
            cin >> m[i][j];

    for (int i = 0; i < SIZE; i++)
        cout << "Sum of the elements at column " << i << " is " << sumColumn(m, 3, i) << endl;

    return 0;
}

例8.2

·(求矩阵主对角线和)编写一个函数,对 n × n n\times n n×n 的双精度值矩阵,求其主对角线上的元素和,函数头如下:
const int SIZE = 4;
double sumMajorDiagonal ( const double m[ ][SIZE] );
编写一个测试程序,读入 4 × 4 4\times4 4×4 的矩阵,打印输出主对角线上的元素和。

#include<iostream>
using namespace std;

const int SIZE = 4;

double sumMajorDiagonal(const double m[][SIZE]){
    double sum = 0;
    for (int i = 0; i < SIZE; i++)
        sum += m[i][i];

    return sum;
}

int main(){
    cout << "Enter a 4-by-4 matrix row by row:" << endl;
    double m[SIZE][SIZE];
    for (int i = 0; i < SIZE; i++)
        for (int j = 0; j < SIZE; j++)
            cin >> m[i][j];

    cout << "Sum of the elements in the major diagonal is " << sumMajorDiagonal(m) << endl;

    return 0;
}

例8.3

·(按成绩给学生排序)重写程序清单8-2,按照回答正确的数目,以升序打印输出学生名单。

#include<iostream>
#include<cmath>
using namespace std;

/** 计算double型数组的均值 */
double mean(double x[], int size){
    double sum = 0;

    for (int i = 0; i < size; i++)
        sum += x[i];

    return sum * 1.0 / size;
}

/** 计算int型数组的均值 */
double mean(int x[], int size){
    int sum = 0;

    for (int i = 0; i < size; i++)
        sum += x[i];

    return sum / size;
}

/** 计算double型数组的偏差 */
double deviation(double x[], int size){
    double mean1 = mean(x, size);
    double squareSum = 0;

    for (int i = 0; i < size; i++)
        squareSum += pow(x[i] - mean1, 2);

    return sqrt(squareSum / (size - 1));
}

/** 计算int型数组的偏差 */
double deviation(int x[], int size){
    double mean1 = mean(x, size);
    double squareSum = 0;

    for (int i = 0; i < size; i++)
        squareSum += pow(x[i] - mean1, 2);

    return sqrt(squareSum / (size - 1));
}

/** 排序数组的方法 */
void sortAndKeepIndex(int list[], int indexList[], int size){
    int currentMax;
    int currentMaxIndex;

    for (int i = 0; i < size; i++)
        indexList[i] = i;

    for (int i = size - 1; i >= 1; i--){
        currentMax = list[i];
        currentMaxIndex = i;

        for (int j = i - 1; j >= 0; j--){
            if (currentMax < list[j]){
                currentMax = list[j];
                currentMaxIndex = j;
            }
        }

        if (currentMaxIndex != i){
            list[currentMaxIndex] = list[i];
            list[i] = currentMax;

            int temp = indexList[i];
            indexList[i] = indexList[currentMaxIndex];
            indexList[currentMaxIndex] = temp;
        }
    }
}

int main(){
    const int NUMBER_OF_STUDENTS = 8;
    const int NUMBER_OF_QUESTIONS = 10;

    char answers[NUMBER_OF_STUDENTS][NUMBER_OF_QUESTIONS] =
            {
                    {'A', 'B', 'A', 'C', 'C', 'D', 'E', 'E', 'A', 'D'},
                    {'D', 'B', 'A', 'B', 'C', 'A', 'E', 'E', 'A', 'D'},
                    {'E', 'D', 'D', 'A', 'C', 'B', 'E', 'E', 'A', 'D'},
                    {'C', 'B', 'A', 'E', 'D', 'C', 'E', 'E', 'A', 'D'},
                    {'A', 'B', 'D', 'C', 'C', 'D', 'E', 'E', 'A', 'D'},
                    {'B', 'B', 'E', 'C', 'C', 'D', 'E', 'E', 'A', 'D'},
                    {'B', 'B', 'A', 'C', 'C', 'D', 'E', 'E', 'A', 'D'},
                    {'E', 'B', 'E', 'C', 'C', 'D', 'E', 'E', 'A', 'D'}
            };

    char keys[NUMBER_OF_QUESTIONS] = {'D', 'B', 'D', 'C', 'C', 'D', 'A', 'E', 'A', 'D'};
    int correctCounts[NUMBER_OF_STUDENTS] = {0, 0, 0, 0, 0, 0, 0, 0};

    for (int i = 0; i < NUMBER_OF_STUDENTS; i++){
        for (int j = 0; j < NUMBER_OF_QUESTIONS; j++){
            if (answers[i][j] == keys[j])
                correctCounts[i]++;
        }
    }

    int indexList[NUMBER_OF_STUDENTS];

    sortAndKeepIndex(correctCounts, indexList, NUMBER_OF_STUDENTS);

    for (int i = 0; i < NUMBER_OF_STUDENTS; i++)
        cout << "Student " << indexList[i] << ": " << correctCounts[i] << endl;

    cout << "Mean is " << mean(correctCounts, NUMBER_OF_STUDENTS) << endl;
    cout << "Deviation is " << deviation(correctCounts, NUMBER_OF_STUDENTS) << endl;

    return 0;
}

例8.4

·(计算员工每周工作时间)假定所有员工的每周工作时间保存在一个二维数组中。每行保存一个员工7天的工作时间。编写一个程序,按周工作总时数递减的次序输出所有员工及他们的周工作总时数。

#include<iostream>
using namespace std;

void sortAndKeepIndex(int list[], int indexList[], int size){
    int currentMax;
    int currentMaxIndex;

    for (int i = 0; i < size; i++)
        indexList[i] = i;

    for (int i = size - 1; i >= 1; i--){
        currentMax = list[i];
        currentMaxIndex = i;

        for (int j = i - 1; j >= 0; j--){
            if (currentMax < list[j]){
                currentMax = list[j];
                currentMaxIndex = j;
            }
        }

        if (currentMaxIndex != i){
            list[currentMaxIndex] = list[i];
            list[i] = currentMax;

            int temp = indexList[i];
            indexList[i] = indexList[currentMaxIndex];
            indexList[currentMaxIndex] = temp;
        }
    }
}

int main(){
    const int NUMBER_OF_WORKERS = 8;
    double workHours[NUMBER_OF_WORKERS][7] = {
            {2, 4, 3, 4, 5, 8, 8},
            {7, 3, 4, 3, 3, 4, 4},
            {3, 3, 4, 3, 3, 2, 2},
            {9, 3, 4, 7, 3, 4, 1},
            {3, 5, 4, 3, 6, 3, 8},
            {3, 4, 4, 6, 3, 4, 4},
            {3, 7, 4, 8, 3, 8, 4},
            {6, 3, 5, 9, 2, 7, 9}
    };

    int weeklyHours[NUMBER_OF_WORKERS] = {0, 0, 0, 0, 0, 0, 0, 0};
    for (int i = 0; i < NUMBER_OF_WORKERS; i++)
        for (int j = 0; j < 7; j++)
            weeklyHours[i] += workHours[i][j];

    int indexList[NUMBER_OF_WORKERS];

    sortAndKeepIndex(weeklyHours, indexList, NUMBER_OF_WORKERS);

    for (int i = NUMBER_OF_WORKERS - 1; i >= 0; i--)
        cout << "Employee " << indexList[i] << ": " <<
             weeklyHours[i] << endl;

    return 0;
}

例8.5

·(代数:矩阵相加)编写一个函数,将两个矩阵 a 和 b 相加,结果存储在矩阵 c 中。
( a 11 a 12 a 13 a 21 a 22 a 23 a 31 a 32 a 33 ) \quad\begin{pmatrix}a_{11}&a_{12}&a_{13}\\a_{21}&a_{22}&a_{23}\\a_{31}&a_{32}&a_{33}\end{pmatrix}\quad a11a21a31a12a22a32a13a23a33 + + + ( b 11 b 12 b 13 b 21 b 22 b 23 b 31 b 32 b 33 ) \quad\begin{pmatrix}b_{11}&b_{12}&b_{13}\\b_{21}&b_{22}&b_{23}\\b_{31}&b_{32}&b_{33}\end{pmatrix}\quad b11b21b31b12b22b32b13b23b33 = = = ( a 11 + b 11 a 12 + b 12 a 13 + b 13 a 21 + b 21 a 22 + b 22 a 23 + b 23 a 31 + b 31 a 32 + b 32 a 33 + b 33 ) \quad\begin{pmatrix}a_{11}+b_{11}&a_{12}+b_{12}&a_{13}+b_{13}\\a_{21}+b_{21}&a_{22}+b_{22}&a_{23}+b_{23}\\a_{31}+b_{31}&a_{32}+b_{32}&a_{33}+b_{33}\end{pmatrix}\quad a11+b11a21+b21a31+b31a12+b12a22+b22a32+b32a13+b13a23+b23a33+b33
函数头如下:
const int N = 3;
void addMatrix ( const double a[ ][N], const double b[ ][N], double c[ ][N] );
每个元素 cij 等于 aij + bij 。编写一个测试程序,提示用户输入两个 3 × 3 3\times3 3×3 的矩阵,打印输出它们的和。

#include<iostream>
#include<iomanip>
using namespace std;

const int N = 3;

void addMatrix(const double a[][N], const double b[][N], double c[][N]){
    for (int i = 0; i < N; i++)
        for (int j = 0; j < N; j++)
            c[i][j] = a[i][j] + b[i][j];
}

void printResult(double a[][N], double b[][N], double c[][N]){
    for (int i = 0; i < N; i++){
        for (int j = 0; j < N; j++)
            cout << left << setw(5) << a[i][j];

        if (i == N / 2)
            cout << "+    ";
        else
            cout << "     ";

        for (int j = 0; j < N; j++)
            cout << left << setw(5) << b[i][j];

        if (i == N / 2)
            cout << "  =    ";
        else
            cout << "       ";

        for (int j = 0; j < N; j++)
            cout << left << setw(5) << c[i][j];

        cout << endl;
    }
}

int main(){
    cout << "Enter matrix1: ";
    double a[N][N];
    for (int i = 0; i < N; i++)
        for (int j = 0; j < N; j++)
            cin >> a[i][j];

    cout << "Enter matrix2: ";
    double b[N][N];
    for (int i = 0; i < N; i++)
        for (int j = 0; j < N; j++)
            cin >> b[i][j];

    double c[N][N];
    cout << "The addition of the matrices is" << endl;
    addMatrix(a, b, c);
    printResult(a, b, c);

    return 0;
}

例8.6

·(金融应用:税款计算)使用数组重写程序清单3-3。对每个纳税身份,有6种税率,每种税率适用于一个特定的收入范围。这6种税率对所有纳税身份都是一样的,可用如下数组表示:
double rates[ ] = {0.10, 0.15, 0.25, 0.28, 0.33, 0.36};
对所有纳税身份,税率适用的收入范围可用一个二维数组表示:
int brackets[4][5] =
{
 {8350, 33950, 82250, 171550, 372950}, // Single filer
 {16700, 67900, 137050, 208850, 372950}, // Married jointly or qualifying widow(er)
 {8350, 33950, 68525, 104425, 186475}, // Married separately
 {11950, 45500, 117450, 190200, 372950} // Head of household
};

#include<iostream>
using namespace std;

double tax(int status, double income){
    double tax = 0;
    double rates[] = {0.10, 0.15, 0.25, 0.28, 0.33, 0.36};
    int brackets[4][5] =
            {
                    {8350, 33950, 82250, 171550, 372950},
                    {16700, 67900, 137050, 208850, 372950},
                    {8350, 33950, 68525, 104425, 186475},
                    {11950, 45500, 117450, 190200, 372950}
            };

    if (income < brackets[status][0]){
        tax = income * rates[0];
        return 0;
    }
    else
        tax = brackets[status][0] * rates[0];

    for (int i = 1; i < 5; i++){
        if (income > brackets[status][i] && i == 4)
            tax = tax + (brackets[status][i] - brackets[status][i - 1]) * rates[i]
                    + (income - brackets[status][i]) * rates[i + 1];
        else if (income > brackets[status][i])
            tax = tax + (brackets[status][i] - brackets[status][i - 1]) * rates[i];
        else{
            tax = tax + (income - brackets[status][i - 1]) * rates[i];
            break;
        }
    }

    return tax;
}

int main(){
    cout << "(0-single filer, 1-married jointly or qualifying widow(er)," << endl
         << "2-married separately, 3-head of household)" << endl;

    cout << "Enter the filing status: ";
    int status;
    cin >> status;

    cout << "Enter the taxable income: ";
    double income;
    cin >> income;

    cout << "Tax is " << tax(status, income) << endl;

    return 0;
}

例8.7

·(检查矩阵)编写一个程序,随机的用 0 和 1 填充一个 4 × 4 4\times4 4×4 的方针,打印输出该矩阵,并且找出全为 0 或 1 的行、列和对角线。

#include<iostream>
#include<ctime>
#include<cstdlib>
using namespace std;

void row(const int s[][4]){
    bool flag = false;
    for (int i = 0; i < 4; i++){
        bool isRowAllZero = true;
        bool isRowAllOne = true;
        for (int j = 0; j < 4; j++){
            if (s[i][j] != 0){
                isRowAllZero = false;
                continue;
            }
            else if (s[i][j] != 1){
                isRowAllOne = false;
                continue;
            }
            if (!isRowAllZero || !isRowAllOne)
                break;
        }
        if (isRowAllZero){
            cout << "All 0's on row " << i << endl;
            flag = true;
        }
        else if (isRowAllOne){
            cout << "All 1's on row " << i << endl;
            flag = true;
        }
    }

    if (!flag)
        cout << "No same numbers on a row" << endl;
}

void column(const int s[][4]){
    bool flag = false;
    for (int i = 0; i < 4; i++){
        bool isColumnAllZero = true;
        bool isColumnAllOne = true;
        for (int j = 0; j < 4; j++){
            if (s[j][i] != 0){
                isColumnAllZero = false;
                continue;
            }
            else if (s[j][i] != 1){
                isColumnAllOne = false;
                continue;
            }
            if (!isColumnAllZero || !isColumnAllOne)
                break;
        }
        if (isColumnAllZero){
            cout << "All 0's on column " << i << endl;
            flag = true;
        }
        else if (isColumnAllOne){
            cout << "All 1's on column " << i << endl;
            flag = true;
        }
    }

    if (!flag)
        cout << "No same numbers on a column" << endl;
}

void majorDiagonal(const int s[][4]){
    bool flag = false;
    bool isMajorAllZero = true;
    bool isMajorAllOne = true;
    for (int i = 0; i < 4; i++){
        if (s[i][i] != 0)
            isMajorAllZero = false;
        else if (s[i][i] != 1)
            isMajorAllOne = false;
    }

    if (isMajorAllZero){
        cout << "All 0's on major diagonal" << endl;
        flag = true;
    }
    else if (isMajorAllOne){
        cout << "All 1's on major diagonal" << endl;
        flag = true;
    }
    if (!flag)
        cout << "No same numbers on the major diagonal" << endl;
}

void subDiagonal(const int s[][4]){
    bool flag = false;
    bool isSubAllZero = true;
    bool isSubAllOne = true;
    for (int i = 0, j = 3; i < 4; i++, j--){
        if (s[i][j] != 0)
            isSubAllZero = false;
        else if (s[i][j] != 1)
            isSubAllOne = false;
    }

    if (isSubAllZero){
        cout << "All 0's on sub-diagonal" << endl;
        flag = true;
    }
    else if (isSubAllOne){
        cout << "All 1's on sub-diagonal" << endl;
        flag = true;
    }
    if (!flag)
        cout << "No same numbers on the sub-diagonal" << endl;
}

int main(){
    srand(time(0));
    int s[4][4];
    for (int i = 0; i < 4; i++)
        for (int j = 0; j < 4; j++)
            s[i][j] = rand() % 2;

    for (int i = 0; i < 4; i++){
        for (int j = 0; j < 4; j++)
            cout << s[i][j] << " ";
        cout << endl;
    }

    row(s);
    column(s);
    majorDiagonal(s);
    subDiagonal(s);
    
    return 0;
}

例8.8

·(对矩阵行洗牌)编写一个函数,对一个二维 int 型数组的行进行洗牌,函数头如下:
void shuffle ( int m[ ][2], int rowSize );
编写一个测试程序,对下面矩阵的行进行洗牌:
int m[ ][2] = {{1, 2}, {3, 4}, {5, 6}, {7, 8}, {9, 10}};

#include<iostream>
#include<ctime>
#include<cstdlib>
using namespace std;

void shuffle(int m[][2], int rowSize){
    srand(time(0));
    for (int i = 0; i < rowSize; i++){
        int t = rand() % rowSize;
        int temp[2] = {m[t][0], m[t][1]};
        m[t][0] = m[i][0];
        m[t][1] = m[i][1];
        m[i][0] = temp[0];
        m[i][1] = temp[1];
    }
}

int main(){
    int m[5][2] = {{1, 2}, {3, 4}, {5, 6}, {7, 8}, {9, 10}};
    shuffle(m, 5);

    cout << "对矩阵行洗牌后: " << endl;
    for (int i = 0; i < 5; i++){
        for (int j = 0; j < 2; j++)
            cout << m[i][j] << " ";
        cout << endl;
    }

    return 0;
}

例8.9

·(代数:矩阵相乘)编写一个函数,将两个矩阵 a a a b b b 相乘,结果存储在矩阵 c c c 中。
( a 11 a 12 a 13 a 21 a 22 a 23 a 31 a 32 a 33 ) \quad\begin{pmatrix}a_{11}&a_{12}&a_{13}\\a_{21}&a_{22}&a_{23}\\a_{31}&a_{32}&a_{33}\end{pmatrix}\quad a11a21a31a12a22a32a13a23a33 × \times × ( b 11 b 12 b 13 b 21 b 22 b 23 b 31 b 32 b 33 ) \quad\begin{pmatrix}b_{11}&b_{12}&b_{13}\\b_{21}&b_{22}&b_{23}\\b_{31}&b_{32}&b_{33}\end{pmatrix}\quad b11b21b31b12b22b32b13b23b33 = = = ( c 11 c 12 c 13 c 21 c 22 c 23 c 31 c 32 c 33 ) \quad\begin{pmatrix}c_{11}&c_{12}&c_{13}\\c_{21}&c_{22}&c_{23}\\c_{31}&c_{32}&c_{33}\end{pmatrix}\quad c11c21c31c12c22c32c13c23c33
函数头如下:
const int N = 3;
void multiplyMatrix ( const double a[ ][N], const double b[ ][N], double c[ ][N] );
每个元素 c i j c_{ij} cij 等于 a i 1 × b 1 j + a i 2 × b 2 j + a i 3 × b 3 j a_{i1}\times b_{1j}+a_{i2}\times b_{2j}+a_{i3}\times b_{3j} ai1×b1j+ai2×b2j+ai3×b3j
编写一个测试程序,提示用户输入两个 3 × 3 3\times3 3×3 的矩阵,打印输出它们的乘积。

#include<iostream>
#include<iomanip>
using namespace std;

const int N = 3;

void multiplyMatrix(const double a[][N], const double b[][N], double c[][N]){
    for (int i = 0; i < N; i++)
        for (int j = 0; j < N; j++)
            c[i][j] = a[i][0] * b[0][j] + a[i][1] * b[1][j] + a[i][2] * b[2][j];
}

void displayResult(double a[][N], double b[][N], double c[][N]){
    for (int i = 0; i < N; i++){
        for (int j = 0; j < N; j++)
            cout << left << setw(6) << a[i][j];

        if (i % 2 == 1)
            cout << "*    ";
        else
            cout << "     ";

        for (int j = 0; j < N; j++)
            cout << left << setw(6) << b[i][j];

        if (i % 2 == 1)
            cout << "=   ";
        else
            cout << "    ";

        for (int j = 0; j < N; j++)
            cout << left << setw(6) << c[i][j];

        cout << endl;
    }
}

int main(){
    cout << "Enter matrix1: ";
    double a[N][N];
    for (int i = 0; i < N; i++)
        for (int j = 0; j < N; j++)
            cin >> a[i][j];

    cout << "Enter matrix2: ";
    double b[N][N];
    for (int i = 0; i < N; i++)
        for (int j = 0; j < N; j++)
            cin >> b[i][j];

    double c[N][N];
    multiplyMatrix(a, b, c);
    cout << "The multiplication of the matrices is" << endl;
    displayResult(a, b, c);

    return 0;
}

例8.10

·(所有最近邻点对)程序清单8-3找到了其中一个最近邻点对。修改该程序,使之能输出所有的最近邻点对(有相同的最小距离)。

#include<iostream>
#include<iomanip>
#include<cmath>
using namespace std;

double getDistance(double x1, double y1, double x2, double y2){
    return sqrt((x2 - x1) * (x2 - x1) + (y2 - y1) * (y2 - y1));
}

int main(){
    cout << "Enter the number of points: ";
    int n;
    cin >> n;
    const int NUMBER_OF_POINTS = n;

    double points[NUMBER_OF_POINTS][2];

    cout << "Enter " << NUMBER_OF_POINTS << " points: ";
    for (int i = 0; i < NUMBER_OF_POINTS; i++)
        cin >> points[i][0] >> points[i][1];

    double shortestDistance = getDistance(points[0][0], points[0][1], points[1][0], points[1][1]);

    for (int i = 0; i < NUMBER_OF_POINTS; i++){
        for (int j = i + 1; j < NUMBER_OF_POINTS; j++){
            double distance = getDistance(points[i][0], points[i][1], points[j][0], points[j][1]);
            if (shortestDistance > distance)
                shortestDistance = distance;
        }
    }

    for (int i = 0; i < NUMBER_OF_POINTS; i++){
        for (int j = i + 1; j < NUMBER_OF_POINTS; j++){
            if (getDistance(points[i][0], points[i][1], points[j][0], points[j][1]) == shortestDistance)
                cout << "The closest two points are " << "(" << fixed << setprecision(1) << points[i][0] << ", " <<
                    points[i][1] << ") and (" << points[j][0] << ", " << points[j][1] << ")" << endl;
        }
    }
    cout << "Their distance is " << setprecision(12) << shortestDistance << endl;

    return 0;
}

例8.11

·(游戏:9枚硬币的正面和反面)9枚硬币放置在 3 × 3 3\times3 3×3 的矩阵中,有些正面朝上,有些反面朝上。可用一个 3 × 3 3\times3 3×3 的矩阵——元素值为0(正面朝上)或1(反面朝上)——来表示9枚硬币的状态。下面是一些例子:
0 0 0  1 0 1  1 1 0  1 0 1  1 0 0 
0 1 0  0 0 1  1 0 0  1 1 0  1 1 1
0 0 0  1 0 0  0 0 1  1 0 0  1 1 0
这9枚硬币的状态可以用一个二进制数字来表示。例如,上面的矩阵分别对应如下数字:000010000  101001100  110100001  101110100  100111110
总共的可能状态数是512,所以你可以用十进制数字0, 1, 2, 3, … , 511来表示矩阵中的所有状态。编写一个程序,提示用户输入一个0 ~ 511的数字,打印输出相应的状态矩阵,用H表示正面朝上,T表示反面朝上。

#include<iostream>
using namespace std;

void toBinaryChars(int number, char binaryChars[]){
    int i = 8;
    while (number != 0){
        if (number % 2 == 0)
            binaryChars[i--] = '0';
        else
            binaryChars[i--] = '1';
        number /= 2;
    }

    for (int k = i; k >= 0; k--)
        binaryChars[k] = '0';
}

int main(){
    cout << "Enter a number between 0 and 511: ";
    int number;
    cin >> number;

    char binaryChars[9];
    toBinaryChars(number, binaryChars);

    for (int i = 1; i <= 9; i++){
        cout << ((binaryChars[i - 1] == '0') ? 'H' : 'T') << " ";
        if (i % 3 == 0)
            cout << endl;
    }

    return 0;
}

例8.12

·(最近邻点对)程序清单8-3是在二维空间中找到最近邻点对。修改该程序,使得它可以找到三维空间中的最近邻点对。使用一个二维数组来表示这些点,用下列点来测试你的程序:
double points[ ][3] = {{-1, 0, 3}, {-1, -1, -1}, {4, 1, 1}, {2, 0.5, 9}, {3.5, 2, -1}, {3, 1.5, 3}, {-1.5, 4, 2}, {5.5, 4, -0.5}};
计算三维空间中两点 ( x 1 , y 1 , z 1 ) (x_1, y_1, z_1) (x1,y1,z1) ( x 2 , y 2 , z 2 ) (x_2, y_2, z_2) (x2,y2,z2) 之间的距离,数学公式为:
( x 2 − x 1 ) 2 + ( y 2 − y 1 ) 2 + ( z 2 − z 1 ) 2 \sqrt{(x_2-x_1)^2+(y_2-y_1)^2+(z_2-z_1)^2} (x2x1)2+(y2y1)2+(z2z1)2

#include<iostream>
#include<iomanip>
#include<cmath>
using namespace std;

double getDistance(double x1, double y1, double z1, double x2, double y2, double z2){
    return sqrt((x2 - x1) * (x2 - x1) + (y2 - y1) * (y2 - y1) + (z2 - z1) * (z2 - z1));
}

int main(){
    double points[8][3] = {{-1, 0, 3}, {-1, -1, -1}, {4, 1, 1}, {2, 0.5, 9},
                           {3.5, 2, -1}, {3, 1.5, 3}, {-1.5, 4, 2}, {5.5, 4, -0.5}};

    double shortestDistance = getDistance(points[0][0], points[0][1], points[0][2],
                                          points[1][0], points[1][1], points[1][2]);

    for (int i = 0; i < 8; i++){
        for (int j = i + 1; j < 8; j++){
            double distance = getDistance(points[i][0], points[i][1], points[i][2],
                                          points[j][0], points[j][1], points[j][2]);
            if (shortestDistance > distance)
                shortestDistance = distance;
        }
    }

    for (int i = 0; i < 8; i++){
        for (int j = i + 1; j < 8; j++){
            if (getDistance(points[i][0], points[i][1], points[i][2],
                            points[j][0], points[j][1], points[j][2]) == shortestDistance)
                cout << "The closest two points are " << "(" << fixed << setprecision(1) << points[i][0] << ", " <<
                     points[i][1] << ", " << points[i][2] << ") and (" << points[j][0] << ", " <<
                     points[j][1] << ", " << points[j][2] << ")" << endl;
        }
    }
    cout << "Their distance is " << setprecision(12) << shortestDistance << endl;

    return 0;
}

例8.13

·(给二维数组排序)编写一个函数,排序一个二维数组,函数头如下:
void sort ( int m[ ][2], int numberOfRows )
该函数对每一行按照第一个元素排序,如果第一个元素相同,则按第二个元素排序。例如,数组{{4, 2}, {1, 7}, {4, 5}, {1, 2}, {1, 1}, {4, 1}}将被排序为{{1, 1}, {1, 2}, {1, 7}, {4, 1}, {4, 2}, {4, 5}}。编写一个测试程序,提示用户输入10个点,调用该函数输出排序后的点。

#include<iostream>
using namespace std;

void sort(int m[][2], int numberOfRows){
    for (int i = 0; i < numberOfRows; i++){
        double currentMin = m[i][0];
        int currentMinIndex = i;

        for (int j = i; j < numberOfRows; j++){
            if (currentMin > m[j][0] || (currentMin == m[j][0] && m[currentMinIndex][1] > m[j][1])){
                currentMin = m[j][0];
                currentMinIndex = j;
            }
        }

        if (currentMinIndex != i){
            int temp0 = m[currentMinIndex][0];
            int temp1 = m[currentMinIndex][1] ;
            m[currentMinIndex][0] = m[i][0];
            m[currentMinIndex][1] = m[i][1];
            m[i][0] = temp0;
            m[i][1] = temp1;
        }
    }
}

void printArray(int m[][2], int numberOfRows){
    for (int i = 0; i < numberOfRows; i++){
        cout << m[i][0] <<", " << m[i][1] << endl;
    }
}

int main(){
    cout << "Enter ten points: ";
    int m[10][2];
    for (int i = 0; i < 10; i++)
        cin >> m[i][0] >> m[i][1];

    sort(m, 10);

    printArray(m, 10);

    return 0;
}

例8.14

·(最大行、列)编写一个程序,随机地用0和1填充一个 4 × 4 4\times4 4×4 的矩阵,输出该矩阵,并且找到有最多1的第一个行和列。下面是样例输出(输出应为The largest row index: 1  The largest column index: 0。——译者注)。
0011
1011
1101
1010
The largest row index: 1
The largest column index: 0

#include<iostream>
#include<ctime>
#include<cstdlib>
using namespace std;

void indexRowColumn(int c[][4]){
    int indexRow = 0;
    int indexColumn = 0;
    int rowOfOneMax = 0;
    int columnOfOneMax = 0;

    for (int i = 0; i < 4; i++){
        int countRow = 0;
        int countColumn = 0;

        for (int j = 0; j < 4; j++){
            if (c[i][j] == 1)
                countRow++;
            if (c[j][i] == 1)
                countColumn++;
        }

        if (countRow > rowOfOneMax){
            rowOfOneMax = countRow;
            indexRow = i;
        }

        if (countColumn > columnOfOneMax){
            columnOfOneMax = countColumn;
            indexColumn = i;
        }
    }

    cout << "The largest row index: " << indexRow << endl;
    cout << "The largest column index: " << indexColumn << endl;
}

int main(){
    srand(time(0));
    int c[4][4];
    for (int i = 0; i < 4; i++)
        for (int j = 0; j < 4; j++)
            c[i][j] = rand() % 2;

    for (int i = 0; i < 4; i++){
        for (int j = 0; j < 4; j++)
            cout << c[i][j];
        cout << endl;
    }

    indexRowColumn(c);

    return 0;
}

例8.15

·(代数: 2 × 2 2\times2 2×2 矩阵的逆)一个方阵 A A A 的逆矩阵记为 A − 1 A^{-1} A1,满足 A × A − 1 = I A\times A^{-1}=I A×A1=I,其中 I I I 是恒等矩阵(对角线为1,其他元素都是0)。例如,矩阵 [ 1 2 3 4 ] \begin{bmatrix}1&2\\3&4\end{bmatrix} [1324]的逆矩阵是 [ − 2 1 1.5 − 0.5 ] \begin{bmatrix}-2&1\\1.5&-0.5\end{bmatrix} [21.510.5],因为有 [ 1 2 3 4 ] × [ − 2 1 1.5 − 0.5 ] = [ 1 0 0 1 ] \begin{bmatrix}1&2\\3&4\end{bmatrix}\times\begin{bmatrix}-2&1\\1.5&-0.5\end{bmatrix}=\begin{bmatrix}1&0\\0&1\end{bmatrix} [1324]×[21.510.5]=[1001]所以一个 2 × 2 2\times2 2×2 的矩阵 A A A 的逆可用下列公式求出(在 a d − b c ! = 0 ad-bc!=0 adbc!=0 的情况下):
A = [ a b c d ] A=\begin{bmatrix}a&b\\c&d\end{bmatrix} A=[acbd] A − 1 = 1 a d − b c [ d − b − c a ] A^{-1}=\frac{1}{ad-bc}\begin{bmatrix}d&-b\\-c&a\end{bmatrix} A1=adbc1[dcba]
实现下列函数,用于计算矩阵的逆:
void inverse ( const double A[ ][2], double inverseOfA[ ][2] )
编写一个测试程序,提示用户输入矩阵的元素 a 、 b 、 c 、 d a、b、c、d abcd,打印输出该矩阵的逆矩阵。

#include<iostream>
#include<iomanip>
using namespace std;

void inverse(const double A[][2], double inverseOfA[][2]){
    double t = 1 / (A[0][0] * A[1][1] - A[0][1] * A[1][0]);
    inverseOfA[0][0] = t * A[1][1];
    inverseOfA[0][1] = t * (-A[0][1]);
    inverseOfA[1][0] = t * (-A[1][0]);
    inverseOfA[1][1] = t * A[0][0];
}

int main(){
    cout << "Enter a, b, c, d: ";
    double A[2][2];
    for (int i = 0; i < 2; i++)
        for (int j = 0; j < 2; j++)
            cin >> A[i][j];

    double a[2][2];
    inverse(A, a);
    for (int i = 0; i < 2; i++){
        for (int j = 0; j < 2; j++)
            cout << fixed << setprecision(1) << a[i][j] << " ";
        cout << endl;
    }

    return 0;
}

例8.16

·(几何:是否共线?)程序设计练习6.20给出了一个函数,可用于检验3个点是否共线。实现下面的函数,检验数组points中的所有点是否共线。
const int SIZE = 2;
bool sameLine ( const double points[ ][SIZE], int numberOfPoints )
编写一个程序,提示用户输入5个点,输出它们是否共线。

#include<iostream>
using namespace std;

const int SIZE = 2;

bool sameLine(const double points[][SIZE], int numberOfPoints){
    for (int i = 0; i < numberOfPoints - 2; i++) {
        for (int j = i + 1; j < numberOfPoints - 1; j++) {
            for (int k = j + 1; k < numberOfPoints; k++) {
                if ((points[j][0] - points[i][0]) * (points[k][1] - points[i][1]) - (points[k][0] - points[i][0])
                    * (points[j][1] - points[i][1]) == 0 && ((points[k][0] > points[i][0] && points[k][0] > points[j][0])
                    || (points[k][0] < points[i][0] && points[k][0] < points[j][0])))
                    return 1;
                else
                    continue;
            }
        }
    }

    return 0;
}

int main(){
    cout << "Enter five points: ";
    double points[5][SIZE];
    for (int i = 0; i < 5; i++)
        for (int j = 0; j < SIZE; j++)
            cin >> points[i][j];

    if (sameLine(points, 5))
        cout << "The five points are on same line" << endl;
    else
        cout << "The five points are not on same line" << endl;

    return 0;
}

例8.17

·(最大元素的位置)编程实现下面的函数,可用于找到一个二维数组中最大元素的位置:
void locateLargest ( const double a[ ][4], int location[ ] )
位置信息存储在一个一维数组location中,它包含2个元素,分别表明二维数组中最大元素所在行和列。编写一个测试程序,提示用户输入一个 3 × 4 3\times4 3×4 的数组,输出最大元素的位置。

#include<iostream>
using namespace std;

void locateLargest(const double a[][4], int location[]){
    double max = 0;
    for (int i = 0; i < 3; i++){
        for (int j = 0; j < 4; j++){
            if (a[i][j] > max){
                max = a[i][j];
                location[0] = i;
                location[1] = j;
            }
        }
    }
}

int main(){
    cout << "Enter the array:" << endl;
    double a[3][4];
    for (int i = 0; i < 3; i++)
        for (int j = 0; j < 4; j++)
            cin >> a[i][j];

    int location[2];
    locateLargest(a, location);

    cout << "The location of the largest element is at (" << location[0] << ", " << location[1] << ")" << endl;

    return 0;
}

例8.18

·(代数: 3 × 3 3\times3 3×3 矩阵求逆)一个方阵 A A A 的逆矩阵记为 A − 1 A^{-1} A1,满足 A × A − 1 = I A\times A^{-1}=I A×A1=I,其中 I I I 是恒等矩阵(对角线为1,其他元素都是0的方阵)。例如,矩阵 [ 1 2 1 2 3 1 4 5 3 ] \begin{bmatrix}1&2&1\\2&3&1\\4&5&3\end{bmatrix} 124235113 的逆矩阵是 [ − 2 0.5 0.5 1 0.5 − 0.5 1 − 1.5 0.5 ] \begin{bmatrix}-2&0.5&0.5\\1&0.5&-0.5\\1&-1.5&0.5\end{bmatrix} 2110.50.51.50.50.50.5 ,即 [ 1 2 1 2 3 1 4 5 3 ] × [ − 2 0.5 0.5 1 0.5 − 0.5 1 − 1.5 0.5 ] = [ 1 0 0 0 1 0 0 0 1 ] \begin{bmatrix}1&2&1\\2&3&1\\4&5&3\end{bmatrix}\times\begin{bmatrix}-2&0.5&0.5\\1&0.5&-0.5\\1&-1.5&0.5\end{bmatrix}=\begin{bmatrix}1&0&0\\0&1&0\\0&0&1\end{bmatrix} 124235113 × 2110.50.51.50.50.50.5 = 100010001 3 × 3 3\times3 3×3 矩阵 A = [ a 11 a 12 a 13 a 21 a 22 a 23 a 31 a 32 a 33 ] A=\begin{bmatrix}a_{11}&a_{12}&a_{13}\\a_{21}&a_{22}&a_{23}\\a_{31}&a_{32}&a_{33}\end{bmatrix} A= a11a21a31a12a22a32a13a23a33 的逆可由下列公式计算(如果 ∣ A ∣ ≠ 0 |A|\neq0 A=0):
A − 1 = 1 ∣ A ∣ [ a 22 a 33 − a 23 a 32 a 13 a 32 − a 12 a 33 a 12 a 23 − a 13 a 22 a 23 a 31 − a 21 a 33 a 11 a 33 − a 13 a 31 a 13 a 21 − a 11 a 23 a 21 a 32 − a 22 a 31 a 12 a 31 − a 11 a 32 a 11 a 22 − a 12 a 21 ] A^{-1}=\frac{1}{|A|}\begin{bmatrix}a_{22}a_{33}-a_{23}a_{32}&a_{13}a_{32}-a_{12}a_{33}&a_{12}a_{23}-a_{13}a_{22}\\a_{23}a_{31}-a_{21}a_{33}&a_{11}a_{33}-a_{13}a_{31}&a_{13}a_{21}-a_{11}a_{23}\\a_{21}a_{32}-a_{22}a_{31}&a_{12}a_{31}-a_{11}a_{32}&a_{11}a_{22}-a_{12}a_{21}\end{bmatrix} A1=A1 a22a33a23a32a23a31a21a33a21a32a22a31a13a32a12a33a11a33a13a31a12a31a11a32a12a23a13a22a13a21a11a23a11a22a12a21 ∣ A ∣ = ∣ a 11 a 12 a 13 a 21 a 22 a 23 a 31 a 32 a 33 ∣ = a 11 a 22 a 33 + a 31 a 12 a 23 + a 13 a 21 a 32 − a 13 a 22 a 31 − a 11 a 23 a 32 − a 33 a 21 a 12 |A|=\begin{vmatrix}a_{11}&a_{12}&a_{13}\\a_{21}&a_{22}&a_{23}\\a_{31}&a_{32}&a_{33}\end{vmatrix}=a_{11}a_{22}a_{33}+a_{31}a_{12}a_{23}+a_{13}a_{21}a_{32}-a_{13}a_{22}a_{31}-a_{11}a_{23}a_{32}-a_{33}a_{21}a_{12} A= a11a21a31a12a22a32a13a23a33 =a11a22a33+a31a12a23+a13a21a32a13a22a31a11a23a32a33a21a12
实现下列函数用于计算矩阵的逆:
void inverse ( const double A[ ][3], double inverseOfA[ ][3] )
编写一个测试程序,提示用户输入矩阵的元素 a 11 , a 12 , a 13 , a 21 , a 22 , a 23 , a 31 , a 32 , a 33 a_{11},a_{12},a_{13},a_{21},a_{22},a_{23},a_{31},a_{32},a_{33} a11,a12,a13,a21,a22,a23,a31,a32,a33,打印输出该矩阵的逆矩阵。

#include<iostream>
using namespace std;

void inverse(const double A[][3], double inverseOfA[][3]){
    double absoluteValueOfA = A[0][0] * A[1][1] * A[2][2] + A[2][0] * A[0][1] * A[1][2] + A[0][2] * A[1][0] * A[2][1]
                            - A[0][2] * A[1][1] * A[2][0] - A[0][0] * A[1][2] * A[2][1] - A[2][2] * A[1][0] * A[0][1];

    inverseOfA[0][0] = (1.0 / absoluteValueOfA) * (A[1][1] * A[2][2] - A[1][2] * A[2][1]);
    inverseOfA[0][1] = (1.0 / absoluteValueOfA) * (A[0][2] * A[2][1] - A[0][1] * A[2][2]);
    inverseOfA[0][2] = (1.0 / absoluteValueOfA) * (A[0][1] * A[1][2] - A[0][2] * A[1][1]);
    inverseOfA[1][0] = (1.0 / absoluteValueOfA) * (A[1][2] * A[2][0] - A[1][0] * A[2][2]);
    inverseOfA[1][1] = (1.0 / absoluteValueOfA) * (A[0][0] * A[2][2] - A[0][2] * A[2][0]);
    inverseOfA[1][2] = (1.0 / absoluteValueOfA) * (A[0][2] * A[1][0] - A[0][0] * A[1][2]);
    inverseOfA[2][0] = (1.0 / absoluteValueOfA) * (A[1][0] * A[2][1] - A[1][1] * A[2][0]);
    inverseOfA[2][1] = (1.0 / absoluteValueOfA) * (A[0][1] * A[2][0] - A[0][0] * A[2][1]);
    inverseOfA[2][2] = (1.0 / absoluteValueOfA) * (A[0][0] * A[1][1] - A[0][1] * A[1][0]);
}

int main(){
    cout << "Enter a11, a12, a13, a21, a22, a23, a31, a32, a33: ";
    double A[3][3];
    for (int i = 0; i < 3; i++)
        for (int j = 0; j < 3; j++)
            cin >> A[i][j];

    double inverseOfA[3][3];
    inverse(A, inverseOfA);

    for (int i = 0; i < 3; i++){
        for (int j = 0; j < 3; j++)
            cout << inverseOfA[i][j] << " ";
        cout << endl;
    }

    return 0;
}

例8.19

·(金融海啸)银行之间会互相借款。在经济困难时期,如果某家银行破产,它就可能无法偿还贷款。一家银行的总资产是它的当前余额加上其向其他银行的借款。
如果一家银行的总资产低于一定程度,该银行将是不安全的。如果一家银行不安全,那么它借的钱就不能还给贷款银行,这样贷款银行在计算总资产时就不能把这部分钱算进去,结果,贷款银行的总资产也可能低于一定程度,可能也是不安全的。编写一个程序,找出所有不安全的银行。程序的输入如下所述,首先读入两个整数 n 和 limit,其中 n 表明有几家银行,limit 是保证银行安全的最少资产数。然后程序读入 n 行数据,分别描述 n 家银行的信息(银行编号从0 ~ n-1)。每行数据的第一个数表示这家银行的余额,第二个数表示共有几家银行从这家银行借款,剩下的为两个数的数对,每对数描述一个借款,第一个数描述借款方的编号,第二个数表示借款总额。假设银行总数最大值为100。(提示:用一个二维数组 loan 表示借款关系。loan[i][j]表示银行 i 给银行 j 的借款额,一旦银行 j 变成不安全,那么 loan[i][j] 应该被置为 0 。)

#include<iostream>
using namespace std;

const int SIZE = 100;

int main(){
    double balances[SIZE]; // 余额
    double loan[SIZE][SIZE]; // 借款

    int n; // 银行数
    cin >> n;

    double limit; // 最少资产数
    cin >> limit;

    for (int i = 0; i < n; i++){
        cin >> balances[i];
        int numberOfBorrowers;
        cin >> numberOfBorrowers;
        for (int j = 0; j < numberOfBorrowers; j++){
            int k; // 银行i给银行k借款
            cin >> k;
            cin >> loan[i][k]; // 银行i向银行k借款的数量
        }
    }

    double asset[SIZE]; // 银行总资产
    bool isSafe[SIZE]; // 最初银行安全状态全为true
    for (int i = 0; i < n; i++)
        isSafe[i] = true;

    cout << "Unsafe banks are ";
    bool newUnsafeFound = true; // 指示是否发现新的不安全银行
    while (newUnsafeFound){
        newUnsafeFound = false; // 假如没有发现新的不安全银行
        for (int i = 0; i < n; i++){
            asset[i] = balances[i];
            for (int j = 0; j < n; j++)
                asset[i] += loan[i][j];

            if (isSafe[i] && asset[i] < limit){ // 发现安全状态为true且总资产低于安全下限的银行
                isSafe[i] = false;
                newUnsafeFound = true; // 继续执行while循环
                cout << i << " ";

                for (int k = 0; k < n; k++)
                    loan[k][i] = 0; // 将所有向银行i借款的对应的银行借款清空,因为银行i还不上了
            }
        }
    }

    return 0;
}

例8.20

·(TicTacToe游戏)所谓TicTacToe游戏,就是两个游戏者轮流在一个 3 × 3 3\times3 3×3 的棋盘的空位中放入代表他们自己的棋子(可用X和O区分)。如果一个游戏者的棋子占据了棋盘的一行、一列或一条对角线,则游戏结束,此游戏者获胜。当所有棋盘格都被填满,而没有任何一方能占据一行、一列或一条对角线,则为平局。编写一个玩TicTacToe游戏的程序,提示第一个游戏者放置一个X棋子,然后提示第二个游戏者放置一个O棋子。每当游戏者放置一个棋子,程序即刷新屏幕显示的棋盘状况,并判断棋局状态(胜、平或尚未结束)。

#include<iostream>
using namespace std;

/** 判断 X 和 O 的状态是否能赢 */
bool isWon(char ch, char board[][3]){
    // 检查所有行
    for (int i = 0; i < 3; i++)
        if (ch == board[i][0] && ch == board[i][1] && ch == board[i][2]) return true;

    // 检查所有列
    for (int j = 0; j < 3; j++)
        if (ch == board[0][j] && ch == board[1][j] && ch == board[2][j]) return true;

    // 检查主对角线
    if (ch == board[0][0] && ch == board[1][1] && ch == board[2][2]) return true;

    // 检查副对角线
    if (ch == board[0][2] && ch == board[1][1] && ch == board[2][0]) return true;

    return false;
}

/** 判断是否下完所有棋盘格子 */
bool isDraw(char board[][3]){
    for (int i = 0; i < 3; i++)
        for (int j = 0; j < 3; j++)
            if (board[i][j] == ' ') return false;

    return true;
}

/** 打印棋盘状况的显示屏幕 */
void displayBoard(char board[][3]){
    cout << "\n-------------" << endl;

    for (int i = 0; i < 3; i++){
        cout << "| " ;
        for (int j = 0; j < 3; j++)
            cout << board[i][j] << " | ";
        cout << "\n-------------" << endl;
    }
}

/** 下棋动作 */
void makeAMove(char board[][3], char player){
    bool done = false;

    do{
        // 提示第一个玩家
        cout << "Enter a row (0, 1, 2) for player " << player << ": ";
        int row;
        cin >> row;

        cout << "Enter a column (0, 1, 2) for player " << player << ": ";
        int column;
        cin >> column;

        if (board[row][column] == ' '){ // 如果此处为空
            board[row][column] = player;
            done = true;
        }
        else
            cout << "This cell is already occupied. Try a different cell" << endl;
    } while (!done); // 当输入一个正确位置之后才退出执行
}

int main(){
    char board[3][3] = {{' ', ' ', ' '}, {' ', ' ', ' '}, {' ', ' ', ' '}}; // 棋盘最初全为空
    displayBoard(board); // 打印棋盘

    while (true){
        // 第一个玩家下棋子
        makeAMove(board, 'X');
        displayBoard(board); // 下完之后打印棋盘
        if (isWon('X', board)){ // 判断玩家1是否能赢
            cout << "X player won" << endl;
            exit(0);
        }
        else if (isDraw(board)){ // 在没有赢家的情况下,判断是否下完所有格子,如果下完了则是平局
            cout << "No winner" << endl;
            exit(0);
        }

        // 第二个玩家下棋子
        makeAMove(board, 'O');
        displayBoard(board); // 下完之后打印棋盘

        if (isWon('O', board)){ // 判断玩家2是否能赢
            cout << "O player won" << endl;
            exit(0);
        }
        else if (isDraw(board)){ // 在没有赢家的情况下,判断是否下完所有格子,如果下完了则是平局
            cout << "No winner" << endl;
            exit(0);
        }
    }

    return 0; // 这一行其实永远不会执行
}

例8.21

·(模式识别:连续4个相同数字)编程实现下面的函数,用于测试一个二维数组是否在水平、垂直或对角方向上含有连续4个相同的数字:
bool isConsecutiveFour ( int values[ ][7] )
编写一个测试程序,提示用户输入二维数组的行数和列数,以及数组元素值。如果该数组含有4个连续相同的数字,则输出为真,否则输出为假。

#include<iostream>
#include<ctime>
#include<cstdlib>
using namespace std;

bool isConsecutiveFour(int values[][7]);
bool isConsecutiveFour(int values[], int size);
const int numberOfRows = 6;
const int numberOfColumns = 7;
const int maxNumberOfElementsInDiagonal = 10;

int main(){
    srand(time(0));
    int board[numberOfRows][numberOfColumns];
    for (int i = 0; i < numberOfRows; i++)
        for (int j = 0; j < numberOfColumns; j++)
            board[i][j] = rand() % 10;

    for (int i = 0; i < numberOfRows; i++){
        for (int j = 0; j < numberOfColumns; j++)
            cout << board[i][j] << " ";
        cout << endl;
    }

    cout << (isConsecutiveFour(board)? "含有4个连续相同的数字" : "不含4个连续相同的数字") << endl;
}

bool isConsecutiveFour(int values[][7]){
    // Check rows
    for (int i = 0; i < numberOfRows; i++){
        if (isConsecutiveFour(values[i], numberOfRows))
            return true;
    }

    // Check columns
    for (int j = 0; j < numberOfColumns; j++){
        int column[numberOfRows];
        // Get a column into an array
        for (int i = 0; i < numberOfRows; i++)
            column[i] = values[i][j];

        if (isConsecutiveFour(column, numberOfRows))
            return true;
    }

    // Check major diagonal (lower part)
    for (int i = 0; i < numberOfRows - 3; i++){
        int numberOfElementsInDiagonal
                = min(numberOfRows - i, numberOfColumns);
        int diagonal[maxNumberOfElementsInDiagonal];
        for (int k = 0; k < numberOfElementsInDiagonal; k++)
            diagonal[k] = values[k + i][k];

        if (isConsecutiveFour(diagonal, numberOfElementsInDiagonal))
            return true;
    }

    // Check major diagonal (upper part)
    for (int j = 1; j < numberOfColumns - 3; j++){
        int numberOfElementsInDiagonal
                = min(numberOfColumns - j, numberOfRows);
        int diagonal[maxNumberOfElementsInDiagonal];
        for (int k = 0; k < numberOfElementsInDiagonal; k++)
            diagonal[k] = values[k][k + j];

        if (isConsecutiveFour(diagonal, numberOfElementsInDiagonal))
            return true;
    }

    // Check sub-diagonal (left part)
    for (int j = 3; j < numberOfColumns; j++){
        int numberOfElementsInDiagonal = min(j + 1, numberOfRows);
        int diagonal[maxNumberOfElementsInDiagonal];

        for (int k = 0; k < numberOfElementsInDiagonal; k++)
            diagonal[k] = values[k][j - k];

        if (isConsecutiveFour(diagonal, numberOfElementsInDiagonal))
            return true;
    }

    // Check sub-diagonal (right part)
    for (int i = 1; i < numberOfRows - 3; i++){
        int numberOfElementsInDiagonal
                = min(numberOfRows - i, numberOfColumns);
        int diagonal[maxNumberOfElementsInDiagonal];

        for (int k = 0; k < numberOfElementsInDiagonal; k++)
            diagonal[k] = values[k + i][numberOfColumns - k - 1];

        if (isConsecutiveFour(diagonal, numberOfElementsInDiagonal))
            return true;
    }

    return false;
}

bool isConsecutiveFour(int values[], int size){
    for (int i = 0; i < size - 3; i++){
        bool isEqual = true;
        for (int j = i; j < i + 3; j++){
            if (values[j] != values[j + 1]){
                isEqual = false;
                break;
            }
        }

        if (isEqual) return true;
    }

    return false;
}

例8.22

·(游戏:四连盘)四连盘是个双人棋盘游戏,游戏双方在一个7列、6行的垂直放置的棋盘上分别安放彩色盘子(棋子)。
游戏的目标是看谁先在某行、某列或某对角方向上形成4个颜色相同的盘子。程序提示游戏双方交替在某一列安放“红色”或“黄色”盘子。当一个盘子放置好后,程序在控制台上刷新输出棋盘情况,并判断游戏状态(胜、平或继续)。

#include<iostream>
using namespace std;

/** 判断 R 和 Y 的状态是否能赢 */
bool isWon(char ch, char board[][7]){
    // 检查所有行
    for (int i = 0; i < 6; i++){
        for (int j = 0; j < 4; j++)
            if (ch == board[i][j] && ch == board[i][j + 1] && ch == board[i][j + 2] && ch == board[i][j + 3]) return true;
    }

    // 检查所有列
    for (int j = 0; j < 7; j++){
        for (int i = 0; i < 3; i++)
            if (ch == board[i][j] && ch == board[i + 1][j] && ch == board[i + 2][j] && ch == board[i + 3][j]) return true;
    }

    // 检查主对角线
    for (int i = 0; i < 3; i++){
        for (int j = 0; j < 4; j++){
            if (ch == board[i][j] && ch == board[i + 1][j + 1] && ch == board[i + 2][j + 2] && ch == board[i + 3][j + 3]) return true;
        }
    }

    // 检查副对角线
    for (int i = 0; i < 3; i++){
        for (int j = 6; j > 2; j--){
            if (ch == board[i][j] && ch == board[i + 1][j - 1] && ch == board[i + 2][j - 2] && ch == board[i + 3][j - 3]) return true;
        }
    }

    return false;
}

/** 判断是否下完所有棋盘格子 */
bool isDraw(char board[][7]){
    for (int i = 0; i < 6; i++)
        for (int j = 0; j < 7; j++)
            if (board[i][j] == ' ') return false;

    return true;
}

/** 打印棋盘状况的显示屏幕 */
void displayBoard(char board[][7]){
    for (int i = 0; i < 6; i++){
        cout << "| " ;
        for (int j = 0; j < 7; j++)
            cout << board[i][j] << " | ";
        cout << endl;
    }
    cout << "-----------------------------" << endl;
}

/** 下棋动作 */
void makeAMove(char board[][7], char player){
    bool done = false;

    do{
        // 提示玩家下棋
        cout << "Drop a "; cout << ((player == 'R') ? "red" : "yellow"); cout << " disk at column (0-6): ";
        int column;
        cin >> column;

        for (int i = 5; i >= 0; i--){
            if (board[i][column] == ' '){ // 如果此处为空
                board[i][column] = player;
                done = true;
                break;
            }
        }
    } while (!done); // 当输入一个正确位置之后才退出执行
}

int main(){
    char board[6][7] = {{' ', ' ', ' ', ' ', ' ', ' ', ' '}, {' ', ' ', ' ', ' ', ' ', ' ', ' '},
                        {' ', ' ', ' ', ' ', ' ', ' ', ' '}, {' ', ' ', ' ', ' ', ' ', ' ', ' '},
                        {' ', ' ', ' ', ' ', ' ', ' ', ' '}, {' ', ' ', ' ', ' ', ' ', ' ', ' '},}; // 棋盘最初全为空
    displayBoard(board); // 打印棋盘

    while (true){
        // 第一个玩家下棋子
        makeAMove(board, 'R');
        displayBoard(board); // 下完之后打印棋盘
        if (isWon('R', board)){ // 判断玩家1是否能赢
            cout << "The red player won" << endl;
            exit(0);
        }
        else if (isDraw(board)){ // 在没有赢家的情况下,判断是否下完所有格子,如果下完了则是平局
            cout << "No winner" << endl;
            exit(0);
        }

        // 第二个玩家下棋子
        makeAMove(board, 'Y');
        displayBoard(board); // 下完之后打印棋盘

        if (isWon('Y', board)){ // 判断玩家2是否能赢
            cout << "The yellow player won" << endl;
            exit(0);
        }
        else if (isDraw(board)){ // 在没有赢家的情况下,判断是否下完所有格子,如果下完了则是平局
            cout << "No winner" << endl;
            exit(0);
        }
    }

    return 0; // 这一行其实永远不会执行
}

例8.23

·(中心城市)给定一些城市的集合,到其他所有城市距离和最小的城市被称为中心城市。编写一个程序,提示用户输入城市数量和位置(坐标),找到中心城市及它到其他城市的距离之和。假设城市数量的最大值为20。

#include<iostream>
#include<cmath>
using namespace std;

double distanceOfCities(double x1, double y1, double x2, double y2){
    double distance = sqrt((x2 - x1) * (x2 - x1) + (y2 - y1) * (y2 - y1));
    return distance;
}

int indexMin(double distance[], int numberOfCities){
    double min = distance[0];
    int indexOfMin = 0;
    for (int i = 1; i < numberOfCities; i++){
        if (min > distance[i]){
            min = distance[i];
            indexOfMin = i;
        }
    }

    return indexOfMin;
}

int main(){
    cout << "Enter the number of cities: ";
    int numberOfCities;
    cin >> numberOfCities;

    cout << "Enter the coordinates of the cities: ";
    double cities[numberOfCities][2];
    for (int i = 0; i < numberOfCities; i++)
        for (int j = 0; j < 2; j++)
            cin >> cities[i][j];

    double distance[numberOfCities];
    for (int i = 0; i < numberOfCities; i++){
        double d = 0;
        for (int j = 0; j < numberOfCities; j++){
            if (j != i)
                d = d + distanceOfCities(cities[i][0], cities[i][1], cities[j][0], cities[j][1]);
        }
        distance[i] = d;
    }

    cout << "The central city is at (" << cities[indexMin(distance, numberOfCities)][0] << ", "
         << cities[indexMin(distance, numberOfCities)][1] << ")" << endl;
    cout << "The total distance to all other cities is " << distance[indexMin(distance, numberOfCities)] << endl;

    return 0;
}

例8.24

·(验证数独解)程序清单8-4通过检查棋盘上的每个数是否合理来验证数独解的正确性。重写这个程序,通过检查每行、每列及每个小块是否含有 1 ~ 9 来验证数独解的正确性。

#include<iostream>
using namespace std;

void readASolution(int grid[][9]);
bool isValid(const int grid[][9]);
bool is1To9(const int list[]);
void selectionSort(int list[], int listSize);

int main(){
    int grid[9][9];
    readASolution(grid);

    cout << (isValid(grid) ? "Valid solution" : "Invalid solution");

    return 0;
}

/** 在键盘上读取一个数独的解 */
void readASolution(int grid[][9]){
    cout << "Enter a Sudoku puzzle:" << endl;
    for (int i = 0; i < 9; i++)
        for (int j = 0; j < 9; j++)
            cin >> grid[i][j];
}

/** 检查是否满足数独要求 */
bool isValid(const int grid[][9]){
    // 检查每一行是否都有数字1~9
    for (int i = 0; i < 9; i++)
        if (!is1To9(grid[i]))
            return false;

    // 检查每一列是否都有数字1~9
    for (int j = 0; j < 9; j++){
        // 获取数组的每一列
        int column[9];
        for (int i = 0; i < 9; i++){
            column[i] = grid[i][j];
        }

        if (!is1To9(column))
            return false;
    }

    // 检查每个3*3空格是否都有数字1~9
    for (int i = 0; i < 3; i++){
        for (int j = 0; j < 3; j++){
            int k = 0;
            int list[9];
            for (int row = i * 3; row < i * 3 + 3; row ++)
                for (int column = j * 3; column < j * 3 + 3; column++)
                    list[k++] = grid[row][column];

            if (!is1To9(list))
                return false;
        }
    }

    return true;
}

/** 检查一维数组是否包含数字1~9 */
bool is1To9(const int list[]){
    int temp[9];
    for (int i = 0; i < 9; i++)
        temp[i] = list[i];

    selectionSort(temp, 9);

    for (int i = 0; i < 9; i++)
        if (temp[i] != i + 1)
            return false;

    return true;
}

/** 选择排序 */
void selectionSort(int list[], int listSize){
    for (int i = 0; i < listSize; i++){
        int currentMin = list[i];
        int currentMinIndex = i;

        for (int j = i + 1; j < listSize; j++){
            if (currentMin > list[j]){
                currentMin = list[j];
                currentMinIndex = j;
            }
        }

        if (currentMinIndex != i){
            list[currentMinIndex] = list[i];
            list[i] = currentMin;
        }
    }
}

例8.25

·(马尔可夫矩阵)一个 n × n n\times n n×n 的矩阵被称为正马尔可夫矩阵,如果每个元素都大于0而且每一列的所有元素和为1。编程实现下面的函数,用于检查一个矩阵是否为马尔可夫矩阵:
const int SIZE = 3;
bool isMarkovMatrix ( const double m[ ][SIZE] );
编写一个测试程序,提示用户输入一个 3 × 3 3\times3 3×3 的双精度值矩阵,验证它是否是一个马尔可夫矩阵。

#include<iostream>
using namespace std;

const int SIZE = 3;

bool isMarkovMatrix(const double m[][SIZE]){
    for (int i = 0; i < SIZE; i++){
        for (int j = 0; j < SIZE; j++){
            if (m[i][j] <= 0)
                return false;
        }
    }

    for (int i = 0; i < SIZE; i++){
        double sum = 0;
        for (int j = 0; j < SIZE; j++)
            sum += m[j][i];
        if (sum != 1)
            return false;
    }

    return true;
}

int main(){
    cout << "Enter a 3 by 3 matrix row by row:" << endl;
    double m[SIZE][SIZE];
    for (int i = 0; i < SIZE; i++)
        for (int j = 0; j < SIZE; j++)
            cin >> m[i][j];

    if (isMarkovMatrix(m))
        cout << "It is a Markov matrix" << endl;
    else
        cout << "It is not a Markov matrix" << endl;

    return 0;
}

例8.26

·(行排序)实现下面的函数,用于对一个二维数组的行进行排序,返回一个新的数组,不改变输入数组。
const int SIZE = 3;
void sortRows ( const double m[ ][SIZE], double result[ ][SIZE] );
编写一个测试程序,提示用户输入一个 3 × 3 3\times3 3×3 的双精度值矩阵,打印输出新排序好的矩阵。

#include<iostream>
using namespace std;

const int SIZE = 3;

void sortRows(const double m[][SIZE], double result[][SIZE]){
    for (int i = 0; i < SIZE; i++)
        for (int j = 0; j < SIZE; j++)
            result[i][j] = m[i][j];

    for (int i = 0; i < SIZE; i++){
        bool changed = true;
        do {
            changed = false;
            for (int j = 0; j < SIZE - 1; j++)
                if (result[i][j] > result[i][j + 1]){
                    double temp = result[i][j + 1];
                    result[i][j + 1] = result[i][j];
                    result[i][j] = temp;
                    changed = true;
                }
        } while(changed);
    }
}

int main(){
    cout << "Enter a 3 by 3 matrix row by row:" << endl;
    double m[SIZE][SIZE];
    for (int i = 0; i < SIZE; i++)
        for (int j = 0; j < SIZE; j++)
            cin >> m[i][j];

    double result[SIZE][SIZE];
    sortRows(m, result);

    cout << "The row-sorted array is" << endl;
    for (int i = 0; i < SIZE; i++){
        for (int j = 0; j < SIZE; j++)
            cout << result[i][j] << " ";
        cout << endl;
    }

    return 0;
}

例8.27

·(列排序)实现下面的函数,用于对一个二维数组的列进行排序,返回一个新的数组,不改变输入数组。
const int SIZE = 3;
void sortColumns ( const double m[ ][SIZE], double result[ ][SIZE] );
编写一个测试程序,提示用户输入一个 3 × 3 3\times3 3×3 的双精度值矩阵,打印输出新排序好的矩阵。

#include<iostream>
using namespace std;

const int SIZE = 3;

void sortColumns(const double m[][SIZE], double result[][SIZE]){
    for (int i = 0; i < SIZE; i++)
        for (int j = 0; j < SIZE; j++)
            result[i][j] = m[i][j];

    for (int j = 0; j < SIZE; j++){
        bool changed = true;
        do {
            changed = false;
            for (int i = 0; i < SIZE - 1; i++)
                if (result[i][j] > result[i + 1][j]){
                    double temp = result[i + 1][j];
                    result[i + 1][j] = result[i][j];
                    result[i][j] = temp;
                    changed = true;
                }
        } while(changed);
    }
}

int main(){
    cout << "Enter a 3 by 3 matrix row by row:" << endl;
    double m[SIZE][SIZE];
    for (int i = 0; i < SIZE; i++)
        for (int j = 0; j < SIZE; j++)
            cin >> m[i][j];

    double result[SIZE][SIZE];
    sortColumns(m, result);

    cout << "The column-sorted array is" << endl;
    for (int i = 0; i < SIZE; i++){
        for (int j = 0; j < SIZE; j++)
            cout << result[i][j] << " ";
        cout << endl;
    }

    return 0;
}

例8.28

·(严格等同数组)两个数组m1和m2,如果它们的对应元素都相同,则称它们是严格等同( s t r i c t l y strictly strictly i d e n t i c a l identical identical)的。编写一个函数,当m1和m2严格等同时,输出为真。函数头如下:
const int SIZE = 3;
bool equals ( const int m1[ ][SIZE], const int m2[ ][SIZE] );
编写一个测试程序,提示用户输入两个 3 × 3 3\times3 3×3 的整型值矩阵,打印输出它们是否严格等同。

#include<iostream>
using namespace std;

const int SIZE = 3;

bool equals(const int m1[][SIZE], const int m2[][SIZE]){
    for (int i = 0; i < SIZE; i++){
        for (int j = 0; j < SIZE; j++){
            if (m1[i][j] != m2[i][j])
                return false;
        }
    }

    return true;
}

int main(){
    cout << "Enter m1: ";
    int m1[SIZE][SIZE];
    for (int i = 0; i < SIZE; i++)
        for (int j = 0; j < SIZE; j++)
            cin >> m1[i][j];

    cout << "Enter m2: ";
    int m2[SIZE][SIZE];
    for (int i = 0; i < SIZE; i++)
        for (int j = 0; j < SIZE; j++)
            cin >> m2[i][j];

    if (equals(m1, m2))
        cout << "Two arrays are strictly identical" << endl;
    else
        cout << "Two arrays are not strictly identical" << endl;

    return 0;
}

例8.29

·(等同数组)两个数组m1和m2,如果它们含有相同的元素,则称它们是等同( i d e n t i c a l identical identical)的。编写一个函数,当m1和m2等同时,输出为真。函数头如下:
const int SIZE = 3;
bool equals ( const int m1[ ][SIZE], const int m2[ ][SIZE] );

#include<iostream>
using namespace std;

const int SIZE = 3;

void bubbleSort(int list[], int listSize){
    bool changed = true;
    do {
        changed = false;
        for (int i = 0; i < listSize - 1; i++)
            if (list[i] > list[i + 1]){
                int temp = list[i + 1];
                list[i + 1] = list[i];
                list[i] = temp;
                changed = true;
            }
    } while(changed);
}

bool equals(const int m1[][SIZE], const int m2[][SIZE]){
    int c1[9];
    int c2[9];
    int t = 0;
    for (int i = 0; i < SIZE; i++){
        for (int j = 0; j < SIZE; j++){
            c1[t] = m1[i][j];
            c2[t] = m2[i][j];
            t++;
        }
    }

    bubbleSort(c1, 9);
    bubbleSort(c2, 9);

    for (int i = 0; i < 9; i++)
        if (c1[i] != c2[i])
            return false;

    return true;
}

int main(){
    cout << "Enter m1: ";
    int m1[SIZE][SIZE];
    for (int i = 0; i < SIZE; i++)
        for (int j = 0; j < SIZE; j++)
            cin >> m1[i][j];

    cout << "Enter m2: ";
    int m2[SIZE][SIZE];
    for (int i = 0; i < SIZE; i++)
        for (int j = 0; j < SIZE; j++)
            cin >> m2[i][j];

    if (equals(m1, m2))
        cout << "Two arrays are identical" << endl;
    else
        cout << "Two arrays are not identical" << endl;

    return 0;
}

例8.30

·(代数:线性方程组求解)编写一个函数,求解下面的 2 × 2 2\times2 2×2 线性方程组:
{ a 00 x + a 01 y = b 0 a 10 x + a 11 y = b 1 \begin{cases}a_{00}x+a_{01}y=b_0\\a_{10}x+a_{11}y=b_1\end{cases} {a00x+a01y=b0a10x+a11y=b1 x = b 0 a 11 − b 1 a 01 a 00 a 11 − a 01 a 10 x=\frac{b_0a_{11}-b_1a_{01}}{a_{00}a_{11}-a_{01}a_{10}} x=a00a11a01a10b0a11b1a01 y = b 1 a 00 − b 0 a 10 a 00 a 11 − a 01 a 10 y=\frac{b_1a_{00}-b_0a_{10}}{a_{00}a_{11}-a_{01}a_{10}} y=a00a11a01a10b1a00b0a10
函数头如下:
const int SIZE = 2;
bool linearEquation ( const double a[ ][SIZE], const double b[ ], double result[ ] );
a 00 a 11 − a 01 a 10 a_{00}a_{11}-a_{01}a_{10} a00a11a01a10 是 0 时,函数返回假,否则返回真。编写测试程序,提示用户输入 a 00 , a 01 , a 10 , a 11 , b 0 , b 1 a_{00}, a_{01}, a_{10}, a_{11}, b_0, b_1 a00,a01,a10,a11,b0,b1,打印输出结果。当 a 00 a 11 − a 01 a 10 a_{00}a_{11}-a_{01}a_{10} a00a11a01a10 为 0 时,输出“该方程组无解”。

#include<iostream>
using namespace std;

const int SIZE = 2;

bool linearEquation(const double a[][SIZE], const double b[], double result[]){
    if (a[0][0] * a[1][1] - a[0][1] * a[1][0] == 0)
        return false;

    result[0] = (b[0] * a[1][1] - b[1] * a[0][1]) / (a[0][0] * a[1][1] - a[0][1] * a[1][0]);
    result[1] = (b[1] * a[0][0] - b[0] * a[1][0]) / (a[0][0] * a[1][1] - a[0][1] * a[1][0]);

    return true;
}

int main(){
    cout << "Enter a00, a01, a10, a11, b0, b1: ";
    double a[SIZE][SIZE];
    for (int i = 0; i < SIZE; i++)
        for (int j = 0; j < SIZE; j++)
            cin >> a[i][j];

    double b[SIZE];
    for (int i = 0; i < SIZE; i++)
        cin >> b[i];

    double result[SIZE];

    if (linearEquation(a, b, result))
        cout << "x is " << result[0] << " and y is " << result[1] << endl;
    else
        cout << "该方程组无解" << endl;

    return 0;
}

例8.31

·(几何:相交点)编写一个函数,返回两条直线的交点。两直线的交点可用程序设计练习3.22中的公式求得。假设 ( x 1 , y 1 ) (x_1, y_1) (x1,y1) ( x 2 , y 2 ) (x_2, y_2) (x2,y2) 是直线1上的两个点, ( x 3 , y 3 ) (x_3, y_3) (x3,y3) ( x 4 , y 4 ) (x_4, y_4) (x4,y4) 是直线2上的两个点。如果方程组无解,则两直线平行。函数头如下:
const int SIZE = 2;
bool getIntersectingPoint ( const double points[ ][SIZE], double result[ ] );
这些点存储在一个 4 × 2 4\times2 4×2 的二维数组 p o i n t s points points 中,( p o i n t s [ 0 ] [ 0 ] , points[0][0], points[0][0], p o i n t s [ 0 ] [ 1 ] points[0][1] points[0][1])即为点 ( x 1 , y 1 ) (x_1, y_1) (x1,y1)。当两直线相交时,函数返回为真,并求得交点坐标。编写一个程序,提示用户输入4个点,输出交点信息。

#include<iostream>
using namespace std;

const int SIZE = 2;

bool getIntersectingPoint(const double points[][SIZE], double result[]){
    double a = points[0][1] - points[1][1];
    double b = -(points[0][0] - points[1][0]);
    double c = points[2][1] - points[3][1];
    double d = -(points[2][0] - points[3][0]);
    double e = a * points[0][0] + b * points[0][1];
    double f = c * points[2][0] + d * points[2][1];

    if (a * d - b * c == 0)
        return false;
    else{
        result[0] = (e * d - b * f) / (a * d - b * c);
        result[1] = (a * f - e * c) / (a * d - b * c);
        return true;
    }
}

int main(){
    cout << "Enter x1, y1, x2, y2, x3, y3, x4, y4: ";
    double points[4][SIZE];
    for (int i = 0; i < 4; i++)
        for (int j = 0; j < SIZE; j++)
            cin >> points[i][j];

    double result[SIZE];

    if (getIntersectingPoint(points, result))
        cout << "The intersecting point is at (" << result[0] << ", " << result[1] << ")" << endl;
    else
        cout << "The two lines are parallel" << endl;

    return 0;
}

例8.32

·(几何:三角形面积)编写一个函数,计算三角形的面积。函数头如下:
const int SIZE = 2;
bool getTriangleArea ( const double points[ ][SIZE] );
三角形顶点存储在一个 3 × 2 3\times2 3×2 的二维数组 p o i n t s points points 中,( p o i n t s [ 0 ] [ 0 ] , points[0][0], points[0][0], p o i n t s [ 0 ] [ 1 ] points[0][1] points[0][1])即为点 ( x 1 , y 1 ) (x_1, y_1) (x1,y1)。三角形面积可用程序设计练习2.19的公式计算。当3点共线时,函数返回0。编写一个程序,提示用户输入3个点,打印输出该三角形面积。

#include<iostream>
#include<cmath>
using namespace std;

const int SIZE = 2;

bool onTheSameLine(const double points[][SIZE]){
    if ((points[1][0] - points[0][0]) * (points[2][1] - points[0][1]) -
        (points[2][0] - points[0][0]) * (points[1][1] - points[0][1]) == 0 &&
        ((points[2][0] > points[0][0] && points[2][0] > points[1][0]) ||
        (points[2][0] < points[0][0] && points[2][0] < points[1][0])))
        return 1;

    return 0;
}

double getTriangleArea(const double points[][SIZE]){
    double side1 = pow(pow(points[1][0] - points[0][0],2) + pow(points[1][1] - points[0][1],2),0.5);
    double side2 = pow(pow(points[2][0] - points[1][0],2) + pow(points[2][1] - points[1][1],2),0.5);
    double side3 = pow(pow(points[2][0] - points[0][0],2) + pow(points[2][1] - points[0][1],2),0.5);
    double s = (side1 + side2 + side3) / 2;
    double area = pow(s * (s - side1) * (s- side2) * (s- side3),0.5);

    return area;
}

int main(){
    cout << "Enter x1, y1, x2, y2, x3, y3: ";
    double points[3][2];
    for (int i = 0; i < 3; i++)
        for (int j = 0; j < SIZE; j++)
            cin >> points[i][j];

    if (onTheSameLine(points))
        cout << "The three points are on the same line" << endl;
    else
        cout << "The area of the triangle is " << getTriangleArea(points) << endl;

    return 0;
}

例8.33

·(几何:多边形的子区域面积)凸四边形可以被分为4个三角形。
编写程序,提示用户输入4个顶点的坐标,按照升序打印输出4个三角形的面积。

#include<iostream>
#include<cmath>
using namespace std;

double getArea(double x1, double y1, double x2, double y2, double x3, double y3){
    double side1 = pow(pow(x2 - x1,2) + pow(y2 - y1,2),0.5);
    double side2 = pow(pow(x3 - x2,2) + pow(y3 - y2,2),0.5);
    double side3 = pow(pow(x3 - x1,2) + pow(y3 - y1,2),0.5);
    double s = (side1 + side2 + side3) / 2;
    double area = pow(s * (s - side1) * (s- side2) * (s- side3),0.5);

    return area;
}

void getIntersectingPoint(const double points[][2], double result[]){
    double a = points[0][1] - points[2][1];
    double b = -(points[0][0] - points[2][0]);
    double c = points[1][1] - points[3][1];
    double d = -(points[1][0] - points[3][0]);
    double e = a * points[0][0] + b * points[0][1];
    double f = c * points[1][0] + d * points[1][1];

    result[0] = (e * d - b * f) / (a * d - b * c);
    result[1] = (a * f - e * c) / (a * d - b * c);
}

void bubbleSort(double list[], int listSize){
    bool changed = true;
    do {
        changed = false;
        for (int i = 0; i < listSize - 1; i++)
            if (list[i] > list[i + 1]){
                double temp = list[i + 1];
                list[i + 1] = list[i];
                list[i] = temp;
                changed = true;
            }
    } while(changed);
}

int main(){
    cout << "Enter x1, y1, x2, y2, x3, y3, x4, y4: ";
    double points[4][2];
    for (int i = 0; i < 4; i++)
        for (int j = 0; j < 2; j++)
            cin >> points[i][j];

    double result[2];
    getIntersectingPoint(points, result);

    cout << result[0] << " " << result[1] << endl;
    double area[4];
    area[0] = getArea(points[0][0], points[0][1], points[1][0], points[1][1], result[0], result[1]);
    area[1] = getArea(points[2][0], points[2][1], points[1][0], points[1][1], result[0], result[1]);
    area[2] = getArea(points[0][0], points[0][1], points[3][0], points[3][1], result[0], result[1]);
    area[3] = getArea(points[2][0], points[2][1], points[3][0], points[3][1], result[0], result[1]);

    bubbleSort(area, 4);

    cout << "The areas are ";
    for (int i = 0; i < 4; i++)
        cout << area[i] << " ";

    return 0;
}

例8.34

·(几何:最右下点)在计算几何中,经常需要寻找一个点集中最靠右下的点。实现下面的函数,返回点集中最右下点:
const int SIZE = 2;
void getRightmostLowestPoint ( const double points[ ][SIZE], int numberOfPoints, double rightMostPoint[ ] );
编写测试程序,提示用户输入6个点,打印输出最靠右下的点。

#include<iostream>
using namespace std;

const int SIZE = 2;

void getRightmostLowestPoint(const double points[][SIZE], int numberOfPoints, double rightMostPoint[]){
    int rightMostIndex = 0;
    double rightMostX = points[0][0];
    double rightMostY = points[0][1];

    for (int i = 1; i < numberOfPoints; i++){
        if (rightMostY > points[i][1]){
            rightMostY = points[i][1];
            rightMostIndex = i;
        }
        else if (rightMostY == points[i][1] && rightMostX < points[i][0]){
            rightMostX = points[i][0];
            rightMostIndex = i;
        }
    }

    rightMostPoint[0] = points[rightMostIndex][0];
    rightMostPoint[1] = points[rightMostIndex][1];
}

int main(){
    cout << "Enter 6 points: ";
    double points[6][2];
    for (int i = 0; i < 6; i++)
        for (int j = 0; j < 2; j++)
            cin >> points[i][j];

    double rightMostPoint[2];
    getRightmostLowestPoint(points, 6, rightMostPoint);

    cout << "The rightmost lowest point is (" << rightMostPoint[0] << ", " << rightMostPoint[1] << ")" << endl;

    return 0;
}

例8.35

·(游戏:寻找更改的元素)假设给定一个 6 × 6 6\times6 6×6 的矩阵,以 0 或 1 填充。所有的行和列都有偶数个 1。让玩家更改一个元素的值(从 1 变到 0 或者从 0 变到 1),编程找出哪个元素被更改了。程序提示用户输入一个 6 × 6 6\times6 6×6 的矩阵(元素值为 0 或 1),找出奇偶性不满足(即 1 的数目不是偶数)的第一个行 r 和第一个列 c,可知被更改的元素位于(r, c)。

#include<iostream>
using namespace std;

int main(){
    cout << "Enter a 6-by-6 matrix row by row:" << endl;
    int c[6][6];
    for (int i = 0; i < 6; i++)
        for (int j = 0; j < 6; j++)
            cin >> c[i][j];

    cout << "The first row and column where the parity is violated is at (";
    for (int i = 0; i < 6; i++){
        int rowOfOne = 0;
        for (int j = 0; j < 6; j++){
            if (c[i][j] == 1)
                rowOfOne++;
        }
        if (rowOfOne % 2 != 0){
            cout << i;
            break;
        }
    }

    cout << ", ";
    for (int j = 0; j < 6; j++){
        int columnOfOne = 0;
        for (int i = 0; i < 6; i++){
            if (c[i][j] == 1)
                columnOfOne++;
        }
        if (columnOfOne % 2 != 0){
            cout << j;
            break;
        }
    }
    cout << ")" << endl;

    return 0;
}

例8.36

·(奇偶性检验)编写程序,生成 6 × 6 6\times6 6×6 的矩阵,以 0 或 1 填充,输出该矩阵,并检查每行、每列是否含有偶数个1。

#include<iostream>
#include<ctime>
#include<cstdlib>
using namespace std;

int main(){
    srand(time(0));
    cout << "Generate a 6-by-6 matrix row by row:" << endl;
    int c[6][6];
    for (int i = 0; i < 6; i++)
        for (int j = 0; j < 6; j++)
            c[i][j] = rand() % 2;

    for (int i = 0; i < 6; i++){
        for (int j = 0; j < 6; j++)
            cout << c[i][j] << " ";
        cout << endl;
    }

    for (int i = 0; i < 6; i++){
        int rowOfOne = 0;
        for (int j = 0; j < 6; j++){
            if (c[i][j] == 1)
                rowOfOne++;
        }
        if (rowOfOne % 2 == 0)
            cout << "第" << i + 1 << "行含有偶数个1" << endl;
    }

    for (int j = 0; j < 6; j++){
        int columnOfOne = 0;
        for (int i = 0; i < 6; i++){
            if (c[i][j] == 1)
                columnOfOne++;
        }
        if (columnOfOne % 2 == 0)
            cout << "第" << j + 1 << "列含有偶数个1" << endl;
    }

    return 0;
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值