C++算法设计与分析例题代码(核心篇)


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];
    }
}
  • 6
    点赞
  • 62
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论
大家好!现在我们将要开始一个穿越“数据结构、算法和程序”这个抽象世界的特殊旅程, 以解决现实生活中的许多难。在程序开发过程中通常需要做到如下两点:一是高效地描述数 据;二是设计一个好的算法,该算法最终可用程序来实现。要想高效地描述数据,必须具备数 据结构领域的专门知识;而要想设计一个好的算法,则需要算法设计领域的专门知识。 在着手研究数据结构和算法设计方法之前,需要你能够熟练地运用C + +编程并分析程序, 这些基本的技能通常是从C + +课程以及其他分散的课程中学到的。本书的前两章旨在帮助你回 顾一下这些技能,其中的许多内容你可能已经很熟悉了。 本章我们将回顾C++ 的一些特性。因为不是针对C++ 新手,因此没有介绍诸如赋值语句、 if 语句和循环语句(如for 和w h i l e)等基本结构,而是主要介绍一些可能已经被你忽略的C + + 特性: • 参数传递方式(如传值、引用和常量引用)。 • 函数返回方式(如返值、引用和常量引用)。 • 模板函数。 • 递归函数。 • 常量函数。 • 内存分配和释放函数:n e w与d e l e t e。 • 异常处理结构:t r y, c a t c h和t h r o w。 • 类与模板类。 • 类的共享成员、保护成员和私有成员。 • 友元。 • 操作符重载。 本章中没有涉及的其他C + +特性将在后续章节中在需要的时候加以介绍。本章还给出了如 下应用程序的代码: • 一维和二维数组的动态分配与释放。 • 求解二次方程。 • 生成n 个元素的所有排列方式。 • 寻找n个元素中的最大值。 此外,本章还给出了如何测试和调试程序的一些技巧。
递归算法兔子繁殖问是一个有趣的数学问,也称为斐波那契数列。问描述如下:从一对兔子开始,它们在出生后的第三个月开始每个月都生一对兔子。小兔子长到第三个月后又能生一对兔子。假设所有兔子都不会死亡,问每个月的兔子总数是多少? 基本思路是使用递归方法来解决这个问。从第一个月开始,兔子的数量依次为1, 1, 2, 3, 5, 8, 13... 可以观察到,从第三个月开始,每个月的兔子数量都是前两个月兔子数量的和,可以用数学公式表示为F(month) = F(month-1) + F(month-2)。 在C语言中,可以使用递归算法来实现这个问。下面是一个示例代码: #include <stdio.h> #include <stdlib.h> int rabbit(int month) { if(month == 1 || month == 2) return 1; else return rabbit(month - 1) + rabbit(month - 2); } int main() { int month; printf("请输入第几个月数:\n"); scanf("%d", &month); printf("第%d月的兔子总数为:%d\n", month, rabbit(month)); system("pause"); return 0; } 递归算法的优点在于它能够简洁地解决问,并且易于理解和实现。然而,递归算法也存在一些缺点,比如在处理大规模问时,递归调用会导致性能问,因为它需要不断地调用自身。此外,递归算法也可能导致栈溢出的问,因为每个递归调用都需要在内存中分配一定的空间。因此,在实际应用中,需要根据具体情况来选择使用递归算法还是其他更适合的方法。<span class="em">1</span><span class="em">2</span><span class="em">3</span> #### 引用[.reference_title] - *1* *2* [递归——兔子繁殖问](https://blog.csdn.net/gml1997/article/details/88806356)[target="_blank" data-report-click={"spm":"1018.2226.3001.9630","extra":{"utm_source":"vip_chatgpt_common_search_pc_result","utm_medium":"distribute.pc_search_result.none-task-cask-2~all~insert_cask~default-1-null.142^v93^chatsearchT3_2"}}] [.reference_item style="max-width: 50%"] - *3* [java算法——斐波那契数列](https://download.csdn.net/download/qq_39854121/11353289)[target="_blank" data-report-click={"spm":"1018.2226.3001.9630","extra":{"utm_source":"vip_chatgpt_common_search_pc_result","utm_medium":"distribute.pc_search_result.none-task-cask-2~all~insert_cask~default-1-null.142^v93^chatsearchT3_2"}}] [.reference_item style="max-width: 50%"] [ .reference_list ]

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

WiChP

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值