C++算法设计与分析例题代码
- (第四章)
- 一、兔子繁殖问题
- 二、求两个整数的最大公约数。
- 三、猴子吃桃问题。
- 四、输出如图4-1所示的杨辉三角形。
- 五、穿越沙漠问题。
- 六、用迭代法求方程组的根。
- 七、牛顿迭代法。
- 八、二分法求解方程f(x)=0根。
- 九、百钱百鸡问题。
- 十、编写算法解如下数字谜。
- 十一、求3个数的最小公倍数。
- 十二、狱吏问题。
- 十三、金块问题。
- 十四、残缺棋盘。
- 十五、求数列的最大字段和。
- 十六、大整数乘法。
- 十七、选择问题1。
- 十八、选择问题2。
- 十九、键盘输入一个高精度的正整数n。
- 二十、数列极差问题。
- 二十一、设计一个算法。
- 二十二、币种统计问题。
- 二十三、取数游戏。
- 二十四、数塔问题。
- 二十五、资源分配问题。
- 二十六、N个矩阵连乘问题。
- 二十七、求两个字符序列的最长公共字符串子序列。
- 二十八、求一个数列的最长不下降子序列。
Wild Chicken Programing TANXL
(第四章)
一、兔子繁殖问题
一对兔子从出生后第三个月开始,每月生一对小兔子。小兔子到第三个月又开始生下一代小兔子。假若兔子只生不死,一月份抱来一对刚出生的小兔子,问一年中每个月各有多少对兔子。
算法设计1:
#include <iostream>
using namespace std;
int main()
{
int i, a{ 1 }, b{ 1 }, c;
cout << "1. " << a << endl << "2. " << b << endl;
for (i = 1; i <= 10; i++)
{
c = a + b;
cout << i + 2 << ". " << c << endl;
a = b;
b = c;
}
}
算法设计2:
#include <iostream>
using namespace std;
int main()
{
int i, a{ 1 }, b{ 1 }, c{};
cout << a << endl << b << endl;
for (i = 1; i <= 4; i++)
{
c = a + b;
a = b + c;
b = c + a;
cout << a << endl << b << endl << c << endl;
}
}
算法设计3:
#include <iostream>
using namespace std;
int main()
{
int i, a{ 1 }, b{ 1 };
cout << a << endl << b << endl;
for (i = 1; i <= 5; i++)
{
a = a + b;
b = a + b;
cout << a << endl << b << endl;
}
}
二、求两个整数的最大公约数。
#include <iostream>
using namespace std;
int main()
{
int a, b, c;
cin >> a >> b;
if (b == 0)
{
cout << "data error";
return 0;
}
else
{
c = a % b;
while (c != 0)
{
a = b;
b = c;
c = a % b;
}
}
cout << b;
return 0;
}
三、猴子吃桃问题。
一只小猴子摘了若干桃子,每天吃现有桃的一半多一个,到第10天时就只有一个桃子了,求原有多少个桃?
#include <iostream>
using namespace std;
int main()
{
int i, a;
a = 1;
for (i = 9; i >= 1; i--)
a = (a + 1) * 2;
cout << a;
}
四、输出如图4-1所示的杨辉三角形。
(限定用1个一维数组完成。)
#include <iostream>
using namespace std;
int main()
{
int n, i, j, a[100];
cout << "请输入三角形的高度 : ";
cin >> n;
cout << "1" << endl;
a[1] = a[2] = 1;
cout << a[2] << " " << a[2] << endl;
for (i = 3; i <= n; i++)
{
a[1] = a[i] = 1;
for (j = i - 1; j > 1; j--)
{
a[j] = a[j] + a[j - 1];
}
for (j = 1; j <= i; j++)
{
cout << a[j] << " ";
}
cout << endl;
}
}
五、穿越沙漠问题。
一辆吉普车穿越1000km的沙漠。吉普车的总装油量为500加仑,耗油率为1加仑/km。由于沙漠中没有油库,必须先用这辆车在沙漠中建立临时油库。若吉普车用最少的耗油量穿越沙漠,应在哪些地方建立油库,以及各处储存的油量。
#include <iostream>
using namespace std;
int main()
{
int dis, k, oil;
dis = 500, k = 1, oil = 500;
do
{
cout << "storepoint " << k << " distance " << 1000 - dis << " oilquantity " << oil << endl;
k++;
dis += 500 / (2 * k - 1);
oil = 500 * k;
} while (dis < 1000);
oil = 500 * (k - 1) + (1000 - dis) * (2 * k - 1);
cout << "storepoint " << k << " distance " << 0 << " oilquantity " << oil << endl;
}
六、用迭代法求方程组的根。
#include<iostream>
#include<cstdio>
#include<cstring>
#include<cmath>
#define eps 1e-8
using namespace std;
const int maxn = 100;
double x[10], y[10];
int main()
{
for (int i = 1; i <= 4; i++)
x[i] = 0;
int cnt = 0;
double c = 0;
do {
for (int i = 1; i <= 4; i++)
y[i] = x[i];
for (int i = 1; i <= 4; i++)
{
x[1] = (6 + x[2] - 2 * x[3]) / 10;
x[2] = (25 + x[1] + x[3] - 3 * x[4]) / 11;
x[3] = (-11 - 2 * x[1] + x[2] + x[4]) / 10;
x[4] = (15 - 3 * x[2] + x[3]) / 8;
}
c = 0;
for (int i = 1; i <= 4; i++)
c += (fabs(y[i] - x[i]));
} while (c > eps && cnt < maxn);
for (int i = 1; i <= 4; i++)
printf("x%d = %.4lf\n", i, x[i]);
}
七、牛顿迭代法。
#include <iostream>
using namespace std;
float f(float a, float b, float c, float d)
{
float x1 = 1, x0, f0, f1;
do
{
x0 = x1;
f0 = ((a * x0 + b) * x0 + c) * x0 + d;
f1 = (3 * a * x0 + 2 * b) * x0 + c;
x1 = x0 - f0 / f1;
} while (fabs(x1 - x0) >= 1e-4);
return x1;
}
int main()
{
float a, b, c, d, fx;
cin >> a >> b >> c >> d;
fx = f(a, b, c, d);
cout << "方程的根为 : " << fx << endl;
}
八、二分法求解方程f(x)=0根。
#include <iostream>
using namespace std;
int main()
{
float x, x1 = 0, x2 = 2, f1, f2, f;
cout << "input x1,x2 (f(x1)*f(x2)<0)" << endl;
cin >> x1 >> x2;
f1 = x1 * x1 * x1 / 2 + 2 * x1 * x1 - 8;
f2 = x2 * x2 * x2 / 2 + 2 * x2 * x2 - 8;
if (f1 * f2 > 0)
{
cout << "Non root" << endl;
return 0;
}
do
{
x = (x1 + x2) / 2;
f = x * x * x / 2 + 2 * x * x - 8;
if (f == 0)
break;
if (f1 * f > 0)
{
x1 = x;
f1 = f;
}
else
x2 = x;
} while (fabs(f) >= 1e-4);
cout << "root = " << x << endl;
}
九、百钱百鸡问题。
中国古代数学家张丘建在他的《算经》中提出了著名的“百钱百鸡问题”:鸡翁一,值钱五;鸡母一,值钱三;鸡雏三,值钱一;百钱买百鸡、翁、母、雏各几何?
算法设计1:
#include <iostream>
using namespace std;
int main()
{
int x, y, z;
for (x = 1; x <= 20; x++)
{
for (y = 1; y <= 34; y++)
{
for (z = 1; z <= 100; z++)
{
if (x + y + z == 100 && 5 * x + 3 * y + z / 3 == 100 && z % 3 == 0)
{
cout << "the cock number is " << x << endl;
cout << "the hen number is " << y << endl;
cout << "the chick number is " << z << endl;
cout << endl;
}
}
}
}
}
算法设计2:
#include <iostream>
using namespace std;
int main()
{
int x, y, z;
for (x = 1; x <= 20; x++)
{
for (y = 1; y <= 33; y++)
{
z = 100 - x - y;
if (z % 3 == 0 && 5 * x + 3 * y + z / 3 == 100)
{
cout << "the cock number is " << x << endl;
cout << "the hen number is " << y << endl;
cout << "the chick number is " << z << endl;
cout << endl;
}
}
}
}
十、编写算法解如下数字谜。
算法设计1:
#include <iostream>
using namespace std;
int main()
{
int A, B, C, i;
long E, E1, F, G1, G2;
for (A = 3; A <= 9; A++)
{
for (B = 0; B <= 9; B++)
{
for (C = 0; C <= 9; C++)
{
F = A * 10000 + B * 1000 + C * 100 + A * 10 + B;
E = F * A;
E1 = E;
G1 = E1 % 10;
for (i = 1; i <= 5; i++)
{
G2 = G1;
E1 = E1 / 10;
G1 = E1 % 10;
if (G1 != G2)
break;
}
if (i == 6)
cout << F << " * " << A << " = " << E << endl;
}
}
}
}
算法设计2:
#include <iostream>
using namespace std;
int main()
{
int A, D;
long E, F;
for (A = 3; A <= 9; A++)
{
for (D = 1; D <= 9; D++)
{
E = D * 100000 + D * 10000 + D * 1000 + D * 100 + D * 10 + D;
if (E % A == 0)
{
F = E / A;
if (F / 10000 == A && (F % 100) / 10 == A)
{
cout << F << " * " << A << " = " << E << endl;
}
}
}
}
}
十一、求3个数的最小公倍数。
#include <iostream>
using namespace std;
int main()
{
int x1, x2, x3, i{ 1 };
cout << "Input 3 number : ";
cin >> x1 >> x2 >> x3;
while (1)
{
if (i % x1 == 0 && i % x2 == 0 && i % x3 == 0)
break;
i++;
}
cout << x1 << " " << x2 << " " << x3 << " least common multiple is " << i;
}
十二、狱吏问题。
某国王大赦囚犯,让一狱吏n次通过一排锁着的n间牢房,每通过一次,按所定规则转动n间牢房中的某些门锁,每转动一次,原来锁着的门被打开,原来打开的门被锁上,通过n次后,门锁开着的,牢房中的犯人放出,否则犯人不得获释。
转动门锁的规则是这样的,第一次通过牢房,从第一间开始要转动每一把门锁,即把全部锁打开;第二次通过牢房时,从第二间开始转动,每隔一间转动一次;… ;第k次通过牢房,从第k间开始转动,每隔k-1间转动一次;问通过n次后,哪些牢房的锁仍然是打开的?
算法设计1:
#include <iostream>
using namespace std;
int main()
{
int i, j, n;
cin >> n;
int* a = (int*)calloc(n + 1, sizeof(int));
for (i = 1; i <= n; i++)
a[i] = 1;
for (i = 1; i <= n; i++)
{
for (j = i; j <= n; j += i)
a[i] = 1 - a[i];
}
for (i = 1; i <= n; i++)
{
if (a[i] == 0)
cout << i << " is free" << endl;
}
}
算法设计2:
#include <iostream>
using namespace std;
int main()
{
int s, i, j, n;
cin >> n;
for (i = 1; i <= n; i++)
{
s = 1;
for (j = 2; j <= i; j++)
{
if (i % j == 0)
s++;
if (s % 2 == 1)
cout << i << " is free" << endl;
}
}
}
算法设计3:
#include <iostream>
using namespace std;
int main()
{
int s, i, j, n;
cin >> n;
for (i = 1; i <= n; i++)
{
if (i * i <= n)
{
cout << i * i << " is free" << endl;
}
else
break;
}
}
十三、金块问题。
老板有一袋金块(共n块,n是2的幂(n≥2)),最优秀的雇员得到其中最重的一块,最差的雇员得到其中最轻的一块。假设有一台比较重量的仪器,希望用最少的比较次数找出最重的和最轻的金块。
算法设计1:
#include <iostream>
using namespace std;
int main()
{
float a[100];
int n;
cin >> n;
for (int i = 1; i <= n; i++)
{
cin >> a[i];
}
float max = a[1];
float min = a[1];
for (int i = 2; i <= n; i++)
{
if (max < a[i])
max = a[i];
else if (min > a[i])
min = a[i];
}
cout << "max : " << max << " min : " << min << endl;
}
算法设计2:
#include <iostream>
using namespace std;
float a[100];
void maxmin(int i, int j, float& fmax, float& fmin)
{
int mid;
float lmax, lmin, rmax, rmin;
if (i == j)
{
fmax = a[i];
fmin = a[i];
}
else if (i == j - 1)
{
if (a[i] < a[j])
{
fmax = a[j];
fmin = a[i];
}
else
{
fmax = a[i];
fmin = a[j];
}
}
else
{
mid = (i + j) / 2;
maxmin(i, mid, lmax, lmin);
maxmin(mid + 1, j, rmax, rmin);
if (lmax > rmax)
fmax = lmax;
else
fmax = rmax;
if (lmin > rmin)
fmin = rmin;
else
fmin = lmin;
}
}
int main()
{
int n;
float fmax{ 0 }, fmin{ 999 };
cin >> n;
for (int i = 1; i <= n; i++)
cin >> a[i];
maxmin(1, n, fmax, fmin);
cout << " max : " << fmax << " min : " << fmin << endl;
}
十四、残缺棋盘。
残缺棋盘是一个有2k×2k(k≥1)个方格的棋盘,其中恰有1个方格残缺。图4-7给出k=1时各种可能的残缺棋盘,其中残缺的方格用阴影表示。
图4-7中的棋盘称作“三格板”,残缺棋盘问题就是要用这4种三格板覆盖更大的残缺棋盘。在此覆盖中要求:
(1)两个三格板不能重叠。
(2)三格板不能覆盖残缺方格,但必须覆盖其他所有的方格。
在这种限制条件下,所需要的三格板总数为(2k×2k-1)/3。
#include <iostream>
using namespace std;
int amount{}, Board[100][100];
int Cover(int tr, int tc, int dr, int dc, int size)
{
int s, t;
if (size < 2)
return 0;
amount++;
t = amount;
s = size / 2;
if (dr < tr + s && dc < tc + s)
{
Cover(tr, tc, dr, dc, s);
Board[tr + s - 1][tc + s] = t;
Board[tr + s][tc + s - 1] = t;
Board[tr + s][tc + s] = t;
Cover(tr, tc + s, tr + s - 1, tc + s, s);
Cover(tr + s, tc, tr + s, tc + s - 1, s);
Cover(tr + s, tc + s, tr + s, tc + s, s);
}
else if (dr < tr + s && dc >= tc + s)
{
Cover(tr, tc + s, dr, dc, s);
Board[tr + s - 1][tc + s - 1] = t;
Board[tr + s][tc + s - 1] = t;
Board[tr + s][tc + s] = t;
Cover(tr, tc, tr + s - 1, tc + s - 1, s);
Cover(tr + s, tc, tr + s, tc + s - 1, s);
Cover(tr + s, tc + s, tr + s, tc + s, s);
}
else if (dr >= tr + s && dc < tc + s)
{
Cover(tr + s, tc, dr, dc, s);
Board[tr + s - 1][tc + s - 1] = t;
Board[tr + s - 1][tc + s] = t;
Board[tr + s][tc + s] = t;
Cover(tr, tc, tr + s - 1, tc + s - 1, s);
Cover(tr, tc + s, tr + s - 1, tc + s, s);
Cover(tr + s, tc + s, tr + s, tc + s, s);
}
else if (dr >= tr + s && dc >= tc + s)
{
Cover(tr + s, tc + s, dr, dc, s);
Board[tr + s - 1][tc + s - 1] = t;
Board[tr + s - 1][tc + s] = t;
Board[tr + s][tc + s - 1] = t;
Cover(tr, tc, tr + s - 1, tc + s - 1, s);
Cover(tr, tc + s, tr + s - 1, tc + s, s);
Cover(tr + s, tc, tr + s, tc + s - 1, s);
}
}
void OutputBoard(int size);
int main()
{
int size{ 1 }, x, y, i, k;
cin >> k;
for (i = 1; i <= k; i++)
size *= 2;
cout << "input incomplete pane :";
cin >> x >> y;
Cover(0, 0, x, y, size);
OutputBoard(size);
}
void OutputBoard(int size)
{
for (int i = 0; i < size; i++)
{
for (int j = 0; j < size; j++)
{
cout << Board[i][j] << " ";
}
cout << endl;
}
}
十五、求数列的最大字段和。
给定n个元素的整数列(可能为负数)a1,a2,…,an。求形如:
ai,ai+1,…,aj i,j=1,…,n i≤j
的子段,使其和为最大。当所有整数均为负整数时定义其最大子段和为0。
#include <iostream>
using namespace std;
int max_sub_sum(int a[], int left, int right);
int max_sum3(int a[], int n)
{
return(max_sub_sum(a, 1, n));
}
int max_sub_sum(int a[], int left, int right)
{
int center, i, left_sum, right_sum, s1, s2, lefts, rights;
if (left == right)
{
if (a[left] > 0)
return a[left];
else
return 0;
}
else
{
center = (left + right) / 2;
left_sum = max_sub_sum(a, left, center);
right_sum = max_sub_sum(a, center + 1, right);
s1 = 0;
lefts = 0;
for (i = center; i >= left; i--)
{
lefts = lefts + a[i];
if (lefts > s1)
s1 = lefts;
}
s2 = 0;
rights = 0;
for (i = center + 1; i <= right; i++)
{
rights = rights + a[i];
if (rights > s2)
s2 = rights;
}
if (s1 + s2 < left_sum && right_sum < left_sum)
return left_sum;
if (s1 + s2 < right_sum)
return right_sum;
return s1 + s2;
}
}
int main()
{
int a[100], n;
cin >> n;
for (int i = 0; i < n; i++)
{
cin >> a[i];
}
cout<<max_sum3(a, n);
}
十六、大整数乘法。
#include <iostream>
using namespace std;
int main()
{
long b, d;
int i, i1, i2, j, k, n{}, n1, n2, a[256];
char s1[256], s2[256];
cin >> s1;
cin >> s2;
for (i = 0; i < 255; i++)
{
a[i] = 0;
}
n1 = strlen(s1);
n2 = strlen(s2);
d = 0;
for (i1 = 0, k = n1 - 1; i1 < n1; i1++, k--)
{
for (i2 = 0, j = n2 - 1; i2 < n2; i2++, j--)
{
i = i1 + i2;
b = a[i] + (s1[k] - 48) * (s2[j] - 48) + d;
a[i] = b % 10;
d = b / 10;
}
while (d > 0)
{
i++;
a[i] = a[i] + d % 10;
d = d / 10;
}
n = i;
}
for (i = n; i >= 0; i--)
cout << a[i];
}
十七、选择问题1。
求一组数的第二小的数据。
#include <iostream>
using namespace std;
float a[100];
float second(int n);
void two(int i, int j, float& fmin2, float& fmin1)
{
float lmin2, lmin1, rmin2, rmin1;
int mid;
if (i == j)
{
fmin2 = a[i];
fmin1 = a[i];
}
else if (i == j - 1)
{
if (a[i] < a[j])
{
fmin2 = a[j];
fmin1 = a[i];
}
else
{
fmin2 = a[i];
fmin1 = a[j];
}
}
else
{
mid = (1 + j) / 2;
two(i, mid, lmin2, lmin1);
two(mid + 1, j, rmin2, rmin1);
if (lmin1 < rmin1)
{
if (lmin2 < rmin1)
{
fmin1 = lmin1;
fmin2 = lmin2;
}
else
{
fmin1 = lmin1;
fmin2 = rmin1;
}
}
else
{
if (rmin2 < lmin1)
{
fmin1 = rmin1;
fmin2 = rmin2;
}
else
{
fmin1 = rmin1;
fmin2 = lmin1;
}
}
}
}
float second(int n)
{
float min1, min2;
two(0, n - 1, min2, min1);
return min2;
}
int main()
{
int n;
float min1, min2;
cin >> n;
for (int i = 0; i < n; i++)
cin >> a[i];
min2 = second(n);
cout << min2;
}
十八、选择问题2。
对于给定的n个元素的数组a[0:n-1],要求从中找出第k小的元素。
#include <iostream>
using namespace std;
int xzwt(int a[], int n, int k);
int select(int a[], int left, int right, int k);
void Swap(int& x, int& y);
int main()
{
int a[100], n, k;
cin >> n;
cin >> k;
for (int i = 0; i < n; i++)
cin >> a[i];
cout << xzwt(a, n, k);
}
int xzwt(int a[], int n, int k)
{
if (k<1 || k>n)
exit(1);
return select(a, 0, n - 1, k);
}
int select(int a[], int left, int right, int k)
{
int i, j, pivot;
if (left >= right)
return a[left];
pivot = a[left];
i = left + 1;
j = right;
while (1)
{
do
{
i++;
} while (a[i] < pivot);
do
{
j--;
} while (a[j] > pivot);
if (i >= j)
break;
Swap(a[i], a[j]);
}
if (j - left + 1 == k)
return pivot;
a[left] = a[j];
a[j] = pivot;
if (j - left + 1 < k)
return select(a, j + 1, right, k - j - 1 + left);
else
return select(a, left, j - 1, k);
}
void Swap(int& x, int& y)
{
int t;
t = x;
x = y;
y = t;
}
十九、键盘输入一个高精度的正整数n。
去掉其中任意s个数字后剩下的数字按原左右次序将组成一个新的正整数。编程对给定的n和s,寻找一种方案使得剩下的数字组成的新数最小。
算法设计1:
#include <iostream>
using namespace std;
char n[100];
void Delete(char n[], int b, int k)
{
int i;
for (i = b; i <= strlen(n) - k; i++)
n[i] = n[i + k];
}
int main()
{
int s, i, j, j1, data[100], len;
cin >> len;
for (i = 0; i < len; i++)
cin >> n[i];
cin >> s;
if (s > len)
{
cout << "data error !";
return 0;
}
j1 = 0;
for (i = 1; i <= s; i++)
{
for (j = 1; j < strlen(n); j++)
{
if (n[j] > n[j + 1])
{
Delete(n, j, 1);
if (j > j1)
data[i] = j + i;
else
data[i] = data[i - 1] - 1;
j1 = j;
break;
}
}
if (j > strlen(n))
break;
}
for (i = i; i <= s; i++)
{
j = len - i + 1;
Delete(n, j, 1);
data[i] = j;
}
while (n[1] == '0' && strlen(n) > 1)
Delete(n, 1, 1);
cout << n;
for (i = 1; i <= s; i++)
cout << data[i] << " ";
}
算法设计2:
#include <iostream>
using namespace std;
void Delete(char n[], int b, int k)
{
int i;
for (i = b; i <= strlen(n) - k; i++)
n[i] = n[i + k];
}
int main()
{
char n[100];
int s, i, j, j1, data[100], len;
cin >> len;
cin >> s;
for (i = 0; i < len; i++)
cin >> n[i];
if (s > len)
{
cout << "data error !";
return 0;
}
i = 0;
j = 1;
j1 = 0;
while (i < s && j <= strlen(n) - 1)
{
while (n[j] <= n[j + 1])
j++;
if (j < strlen(n))
{
Delete(n, j, i);
if (j > j1)
data[i] = j + i;
else
data[i] = data[i - 1] - 1;
i++;
j1 = j;
j--;
}
}
for (i = i; i <= s; i++)
{
j = len - i + 1;
Delete(n, j, 1);
data[i] = j;
}
while (n[1] == '0' && strlen(n) > 1)
Delete(n, 1, 1);
cout << n << endl;
for (i = 1; i <= s; i++)
cout << data[i] << " ";
}
二十、数列极差问题。
在黑板上写了n个正整数排成的一个数列,进行如下操作:每次擦去其中两个数a和b,然后在数列中加入一个数a×b+1,如此下去直至黑板上剩下一个数,在所有按这种操作方式最后得到的数中,最大的记作max,最小的记作min,则该数列的极差定义为m=max-min。
#include <iostream>
using namespace std;
int s1, s2;
void max2(int a[], int n);
void min2(int a[], int n);
inline int calculatemin(int a[], int n)
{
while (n > 2)
{
max2(a, n);
a[s1] = a[s1] * a[s2] + 1;
a[s2] = a[n];
n--;
}
return(a[1] * a[2] + 1);
}
void max2(int a[], int n)
{
int j;
if (a[1] >= a[2])
{
s1 = 1;
s2 = 2;
}
else
{
s1 = 2;
s2 = 1;
}
for (j = 3; j <= n; j++)
{
if (a[j] > a[s1])
{
s2 = s1;
s1 = j;
}
else if (a[j] > a[s2])
s2 = j;
}
}
inline int calculatemax(int a[], int n)
{
while (n > 2)
{
min2(a, n);
a[s1] = a[s1] * a[s2] + 1;
a[s2] = a[n];
n--;
}
return(a[1] * a[2] + 1);
}
void min2(int a[], int n)
{
int j;
if (a[1] <= a[2])
{
s1 = 1;
s2 = 2;
}
else
{
s1 = 2;
s2 = 1;
}
for (j = 3; j <= n; j++)
{
if (a[j] < a[s1])
{
s2 = s1;
s1 = j;
}
else if (a[j] < a[s2])
s2 = j;
}
}
int main()
{
int j, n, a[100], b[100], max, min;
cout << "How many data ?";
cin >> n;
cout << "Input thesr data ";
for (j = 1; j <= n; j++)
{
cin >> a[j];
b[j] = a[j];
}
min = calculatemin(a, n);
max = calculatemax(b, n);
cout << min << " " << max;
}
二十一、设计一个算法。
把一个真分数表示为埃及分数之和的形式。即所谓埃及分数,是指分子为1的分数。如7/8=1/2+1/3+1/24。
#include <iostream>
using namespace std;
int main()
{
int a, b, c;
cout << "input element ";
cin >> a;
cout << "input denominator ";
cin >> b;
if (a >= b)
cout << "input error";
else
{
if (a == 1 || b % a == 0)
cout << a << "/" << b << " = 1 / " << b / a;
else
{
while (a != 1)
{
c = b/a + 1;
a = a * c - b;
b = b * c;
cout << "1/" << c;
if (a > 1)
cout << "+";
if (b % a == 0 || a == 1)
{
cout << "1/" << b / a;
a = 1;
}
}
}
}
}
二十二、币种统计问题。
某单位给每个职工发工资(精确到元)。为了保证避免临时兑换零钱,且取款的张数最少,取工资前要统计出所有职工的工资所需各种币值(100,50,20,10,5,2,1元共7种)的张数。请编程完成。
#include <iostream>
using namespace std;
int main()
{
int i, j, n, GZ, A, B[8] = { 0,100,50,20,10,5,2,1 }, S[8]{ 0 };
cin >> n;
for (i = 1; i <= n; i++)
{
cin >> GZ;
for (j = 1; j <= 7; j++)
{
A = GZ / B[j];
S[j] = S[j] + A;
GZ = GZ - A * B[j];
}
for (i = 1; i <= 7; i++)
cout << B[i] << "----" << S[i] << endl;
}
}
二十三、取数游戏。
有2个人轮流取2n个数中的n个数,所取数之和大者为胜。请编写算法,让先取数者胜,模拟取数过程。
#include <iostream>
using namespace std;
int main()
{
int i, n, s1, s2, data;
cin >> n;
s1 = 0;
s2 = 0;
for (i = 1; i <= n; i++)
{
cin >> data;
if (i % 2 == 0)
s2 += data;
else
s1 += data;
}
if (s1 > s2)
cout << "First take left";
else
cout << "First take right";
}
二十四、数塔问题。
如图4-12所示的一个数塔,从顶层走到底层或从底层到顶层,在每一结点可以选择向左走或是向右走,要求找出一条路径,使路径上的数值和最大。
#include <iostream>
using namespace std;
int main()
{
int a[50][50][3], i, j, n;
cout << "Please input the number of rows: ";
cin >> n;
for (i = 1; i <= n; i++)
{
for (j = 1; j <= i; j++)
{
cin >> a[i][j][1];
a[i][j][2] = a[i][j][1];
a[i][j][3] = 0;
}
}
for (i = n - 1; i >= 1; i--)
{
for (j = 1; j <= i; j++)
{
if (a[i + 1][j][2] > a[i + 1][j + 1][2])
{
a[i][j][2] += a[i + 1][j][2];
a[i][j][3] = 0;
}
else
{
a[i][j][2] += a[i + 1][j + 1][2];
a[i][j][3] = 1;
}
}
}
cout << " max = " << a[1][1][2] << endl;
j = 1;
for (i = 1; i <= n - 1; i++)
{
cout << a[i][j][1] << "->";
j += a[i][j][3];
}
cout << a[n][j][1];
}
二十五、资源分配问题。
设有资源n(n为整数),分配给m个项目,gi(x)为第i个项目分得资源x(x为整数)所得到的利润。求总利润最大的资源分配方案,也就是解下列问题:
max z=g1(x1)+g2(x2)+…+gm(xm)
x1+x2+x3+…+xm+=n,0≤xi≤n 且xi为整数,i=1,2,3,…,m
函数gi(x)以数据表的形式给出。
例如:现有n=7万元投资到A,B,C 3个项目,利润表见表4-4。求总利润最大的资源分配方案。
#include <iostream>
using namespace std;
int main()
{
int i, j, k, m, n, rest, a[100][100], gain[100];
float q[100], f[100], temp[100];
cout << "How many item ?";
cin >> m;
cout << "How many money ?";
cin >> n;
cout << "input one item gain table : ";
for (j = 0; j <= n; j++)
{
cin >> q[j];
f[j] = q[j];
}
for (j = 0; j <= n; j++)
a[1][j] = j;
for (k = 2; k <= m; k++)
{
cout << "input another item gain table : ";
for (j = 0; j <= n; j++)
{
temp[j] = q[j];
cin >> q[j];
a[k][j] = 0;
}
for (j = 0; j <= n; j++)
{
for (i = 0; i <= j; i++)
{
if (f[j - i] + q[i] > temp[j])
{
temp[j] = f[j - i] + q[i];
a[k][j] = i;
}
}
}
for (j = 0; j <= n; j++)
f[j] = temp[j];
}
rest = n;
for (i = m; i >= 1; i--)
{
gain[i] = a[i][rest];
rest = rest - gain[i];
}
for (i = 1; i <= m; i++)
cout << gain[i] << " ";
cout << f[n];
}
二十六、N个矩阵连乘问题。
算法设计1:
#include <iostream>
using namespace std;
int r[100], com[100][100];
int course(int i, int j)
{
int u, t;
if (i == j)
{
com[i][j] = 0;
return NULL;
}
if (i == j - 1)
{
com[i][i + 1] = i;
return (r[i] * r[i + 1] * r[i + 2]);
}
u = course(i, i) + course(i + 1, j) + r[i] * r[i + 1] * r[j + 1];
com[i][j] = i;
for (int k = i + 1; k < j; k++)
{
t = course(i, k) + course(k + 1, j) + r[i] * r[k + 1] * r[j + 1];
if (t < u)
{
u = t;
com[i][j] = k;
}
}
return u;
}
int main()
{
int n, i;
cout << "How many matrixes ?";
cin >> n;
cout << "How size every matrixes ?";
for (i = 1; i <= n + 1; i++)
cin >> r[i];
cout << "The least calculate quantity : " << course(1, n);
for (i = 1; i <= n; i++)
{
cout << endl;
for (int j = 1; j <= n; j++)
cout << com[i][j];
}
}
算法设计2:
#include <iostream>
using namespace std;
int m[100][100], com[100][100], r[100];
int course(int i, int j)
{
int u, k, t;
if (m[i][j] >= 0)
return m[i][j];
if (i == j)
return 0;
if (i == j - 1)
{
com[i][i + 1] = i;
m[i][j] = r[i] * r[i + 1] * r[i + 2];
return m[i][j];
}
u = course(i, i) + course(i + 1, j) + r[i] * r[i + 1] * r[j + 1];
com[i][j] = i;
for (k = i + 1; k < j; k++)
{
t = course(i, k) + course(k + 1, j) + r[i] * r[k + 1] + r[j + 1];
if (t < u)
{
u = t;
com[i][j] = k;
}
}
m[i][j] = u;
return u;
}
int main()
{
int n;
cout << "How many matrixes ?";
cin >> n;
cout << "How size every matrixe ?";
for (int i = 1; i <= n + 1; i++)
cin >> r[i];
for (int i = 1; i <= n; i++)
{
for (int j = 1; j <= n; j++)
{
com[i][j] = 0;
m[i][j] = -1;
}
}
course(1, n);
cout << "The least calculate quantity : " << m[1][n];
for (int i = 1; i <= n; i++)
{
cout << endl;
for (int j = 1; j <= n; j++)
cout << com[i][j];
}
}
算法设计3:
#include <iostream>
using namespace std;
int main()
{
int n, r[100], m[100][100], com[100][100];
cout << "How many matrixes ?";
cin >> n;
cout << "How size every matrixes ?";
for (int i = 1; i <= n + 1; i++)
cin >> r[i];
for (int i = 1; i <= n; i++)
for (int j = 1; j <= n; j++)
com[i][j] = 0;
for (int i = 1; i < n; i++)
{
m[i][i] = 0;
m[i][i + 1] = r[i] * r[i + 1] * r[i + 2];
com[i][i + 1] = i;
}
m[n][n] = 0;
for (int s = 2; s <= n - 1; s++)
{
for (int i = 1; i < n - s - i; i++)
{
int j = i + s;
m[i][j] = m[i][i] + m[i + 1][j] + r[i] * r[i + 1] * r[j + 1];
com[i][j] = i;
for (int k = i + 1; k < j; k++)
{
int t = m[i][k] + m[k + 1][j] + r[i] * r[k + 1] * r[j + 1];
if (t < m[i][j])
{
m[i][j] = t;
com[i][j] = k;
}
}
}
}
cout << "The least calculate quantity " << m[1][n];
for (int i = 1; i <= n; i++)
{
cout << endl;
for (int j = 1; j <= n; j++)
cout << com[i][j];
}
}
二十七、求两个字符序列的最长公共字符串子序列。
#include <iostream>
using namespace std;
int com[100][100];
char a[100], b[100], c[100][100], str[100];
int lcs_len(int i, int j)
{
int t1, t2;
if (i == 0 || j == 0)
c[i][j] = 0;
else
{
if (a[i - 1] == b[j - 1])
c[i][j] = lcs_len(i - 1, j - 1) + 1;
else
{
t1 = lcs_len(i, j - 1);
t2 = lcs_len(i - 1, j);
if (t1 > t2)
c[i][j] = t1;
else
c[i][j] = t2;
}
}
return c[i][j];
}
void buile_lcs(int k, int i, int j)
{
if (i == 0 || j == 0)
return;
if (c[i][j] == c[i - 1][j])
buile_lcs(k, i - 1, j);
else if (c[i][j] == c[i][j - 1])
buile_lcs(k, i, j - 1);
else
{
str[k - 1] = a[i - 1];
buile_lcs(k - 1, i - 1, j - 1);
}
}
int main()
{
int m, n, k;
cout << "Enter two string ";
cin >> a >> b;
m = strlen(a);
n = strlen(b);
k = lcs_len(n, m);
buile_lcs(k, n, m);
cout << str;
}
二十八、求一个数列的最长不下降子序列。
#include <iostream>
using namespace std;
int maxn = 100;
int a[100], b[100], c[100];
int main()
{
int n, i, j, max, p;
cin >> n;
for (i = 1; i <= n; i++)
{
cin >> a[i];
b[i] = 1;
c[i] = 0;
}
for (i = n - 1; i >= 1; i--)
{
max = 0;
p = 0;
for (j = i + 1; i <= n; j++)
{
if (a[i]<a[j] && b[j]>max)
{
max = b[j];
p = j;
}
}
if (p != 0)
{
b[i] = b[p] + 1;
p = i;
}
}
max = 0;
p = 0;
for (i = 1; i <= n; i++)
{
if (b[i] > max)
{
max = b[i];
p = i;
}
}
cout << "maxlong = " << max;
cout << "result is :";
while (p != 0)
{
cout << a[p];
p = c[p];
}
}