例题目录
例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}
(x2−x1)2+(y2−y1)2+(z2−z1)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}
A−1,满足
A
×
A
−
1
=
I
A\times A^{-1}=I
A×A−1=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.51−0.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.51−0.5]=[1001]所以一个
2
×
2
2\times2
2×2 的矩阵
A
A
A 的逆可用下列公式求出(在
a
d
−
b
c
!
=
0
ad-bc!=0
ad−bc!=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}
A−1=ad−bc1[d−c−ba]
实现下列函数,用于计算矩阵的逆:
void inverse ( const double A[ ][2], double inverseOfA[ ][2] )
编写一个测试程序,提示用户输入矩阵的元素
a
、
b
、
c
、
d
a、b、c、d
a、b、c、d,打印输出该矩阵的逆矩阵。
#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}
A−1,满足
A
×
A
−
1
=
I
A\times A^{-1}=I
A×A−1=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.5−1.50.5−0.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.5−1.50.5−0.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}
A−1=∣A∣1
a22a33−a23a32a23a31−a21a33a21a32−a22a31a13a32−a12a33a11a33−a13a31a12a31−a11a32a12a23−a13a22a13a21−a11a23a11a22−a12a21
∣
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+a13a21a32−a13a22a31−a11a23a32−a33a21a12
实现下列函数用于计算矩阵的逆:
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=a00a11−a01a10b0a11−b1a01
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=a00a11−a01a10b1a00−b0a10
函数头如下:
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}
a00a11−a01a10 是 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}
a00a11−a01a10 为 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;
}