合肥工业大学 程序设计艺术与方法实验报告( STL 的熟悉与使用 搜索算法的实现 计算几何算法的实现 动态规划算法的实现)

本实验报告包括四个实验内容:
1.STL 的熟悉与使用
2.搜索算法的实现
3.计算几何算法的实现
4.动态规划算法的实现

实验一、STL 的熟悉与使用

(1) 练习vector 和list 的使用。
定义一个空的vector,元素类型为int,生成10 个随机数插入到vector 中,用迭代
器遍历vector 并输出其中的元素值。在vector 头部插入一个随机数,用迭代器遍历vector
并输出其中的元素值。用泛型算法find 查找某个随机数,如果找到便输出,否则将此数
插入vector 尾部。用泛型算法sort 将vector 排序,用迭代器遍历vector 并输出其中的元
素值。删除vector 尾部的元素,用迭代器遍历vector 并输出其中的元素值。将vector 清
空。
定义一个list,并重复上述实验,并注意观察结果。
(2) 练习泛型算法的使用。
定义一个vector,元素类型为int,插入10 个随机数,使用sort 按升序排序,输出
每个元素的值,再按降叙排序,输出每个元素的值。练习用find 查找元素。用min 和
max 找出容器中的最小元素个最大元素,并输出。

(1)练习vector 和list 的使用。
vector:
源代码:

#include 
#include  //动态数组
#include 
#include     
using namespace std; 
int main() 
{ 
	srand((unsigned)time(NULL)); 
	vector<int> a;    
	vector<int>::iterator it; 
	for (int i = 0; i < 10; i++) 
	{ 
		a.push_back(rand() % 100); 
	} 
	cout << "已随机插入数组a中十个数:"; 
	//输出数组a中的元素 
	for (it = a.begin(); it != a.end(); it++) 
	{ 
		cout << *it << " ";   //迭代器输出 
	} 
	cout << endl << "在数组a的头部插入一个随机数:"; 
	int num_insert = rand() % 100;     
	cout << num_insert << endl; 
	it = a.begin(); 
	a.insert(it, num_insert); //插入该100以内的随机数; 
	cout << "插入后容器内的元素为:"; 
	for (it=a.begin(); it != a.end(); it++) 
	{ 
		cout << *it << " ";   
	} 
	int num_seek = rand() % 100; 
	cout << endl << "查找随机数:" << num_seek; 
	it = find(a.begin(), a.end(), num_seek); 
	if (it != a.end()) 
		cout << endl << "已查找到" << num_seek; 
	else { 
		cout << endl << "未查找到" << num_seek << ",将其插入vector尾端"; 
		a.push_back(num_seek); 
	} 
	sort(a.begin(), a.end()); 
	cout << endl << "泛型算法sort排序:"; 
	//输出排序后的数组a中的元素 
	for (it = a.begin(); it != a.end(); it++) 
	{ 
		cout << *it << " ";   
	} 
	it = a.end() - 1; 
	cout << endl << "删除vector其尾端值" << *it; 
	a.pop_back(); 
	cout << endl << "删除后其容器内的元素为:"; 
	for (it = a.begin(); it != a.end(); it++) 
	{ 
		cout << *it << " ";   
	} 
	a.clear();
	cout << endl; 
	return 0; 
}

List
源代码:
#include 
#include//带头节点的双向循环链表 
#include 
#include 
using namespace std; 
int main() 
{ 
	srand((unsigned)time(NULL)); //创建时间随机种子 
	list<int> a;             
	for (int i = 0; i < 10; i++) 
		a.push_back(rand() % 100); 
	cout << "已插入10个100以内的随机数:"; 
	list<int>::iterator it;   
	for (it = a.begin(); it != a.end(); it++) 
		cout << *it << " ";      
	int num_insert = rand() % 100;  
	cout << endl << "在list容器的头部插入一个随机数:" << num_insert << endl; 
	a.push_front(num_insert);    
	cout << "插入随机数" << num_insert << ",list容器中的元素现为:"; 
	for (it = a.begin(); it != a.end(); it++) 
		cout << *it << " ";      
	int num_seek = rand() % 100;  
	cout << endl << "在list容器中查找随机数:" << num_seek << endl; 
	it = find(a.begin(), a.end(), num_seek);  
	if (it != a.end()) 
	{ 
		cout << "list容器中存在" << num_seek << ",插入该随机值。" << endl; 
		a.push_back(num_seek); 
	} 
	else 
		cout << "list容器中不存在" << num_seek << endl; 
	a.sort();
	cout << "泛型算法sort函数排序后list容器中元素为:"; 
	for (it = a.begin(); it != a.end(); it++) 
		cout << *it << " ";    
	cout << endl; 
	a.pop_back(); 
	cout << "删除最后一位后,list容器中元素为:"; 
	for (it = a.begin(); it != a.end(); it++) 
		cout << *it << " ";  
	cout << endl; 
	a.clear();
	return 0; 
}

1)	练习泛型算法的使用。
源代码:
#include 
#include 
#include 
#include 
using namespace std; 
vector<int> a; 
int main() 
{ 
	vector<int>::iterator it; 
	srand((unsigned)time(NULL)); //创建时间随机种子 
	for (int i = 0; i < 10; i++) 
	{ 
		a.push_back(rand() % 100); 
	} 
	cout << "已随机插入10个数为:"; 
	for (it = a.begin(); it != a.end(); it++) 
	{ 
		cout << *it << " "; 
	} 
	sort(a.begin(), a.end());//升序排序; 
	cout << endl << "使用sort升序排序:"; 
	for (it = a.begin(); it != a.end(); it++) 
	{ 
		cout << *it << " "; 
	} 
	sort(a.begin(), a.end(), greater<int>());//降序 
	cout << endl << "使用sort降序排序:"; 
	for (it = a.begin(); it != a.end(); it++) 
	{ 
		cout << *it << " "; 
	} 
	int num_seek = rand() % 100; 
	//判断是否存在随机值 
	it = find(a.begin(), a.end(), num_seek); 
	cout << endl<< "查找随机数:" << num_seek; 
	if (it!=a.end())  
		cout << ",找到该随机数" << num_seek; 
	else 
		cout << ",容器中不存在该随机数" << endl; 
	cout << "容器中最小值为;" << *min_element(a.begin(), a.end());  
	cout << "容器中最大值为;" << *max_element(a.begin(), a.end()); 
	cout << endl; 
	return 0; 
}

实验二、搜索算法的实现

  1. 将书上的走迷宫代码上机运行并检验结果,并注意体会搜索的思想。
    2.八皇后问题:在一个国际象棋棋盘上放八个皇后,使得任何两个皇后之间不相互攻击,求出所有的布棋方法。上机运行并检验结果。

  2. 骑士游历问题:在国际棋盘上使一个骑士遍历所有的格子一遍且仅一遍,对于任意给定的顶点,输出一条符合上述要求的路径。
    4.倒水问题:给定2 个没有刻度容器,对于任意给定的容积,求出如何只用两个瓶装出L 升
    的水,如果可以,输出步骤,如果不可以,请输出No Solution。

  3. 八皇后问题
    1.1思路分析:
    设立数组a[n],数组下标对应棋盘的行;数组存储的值为列;数组的每个下标(列)对应相应的行;
    递归遍历所有的棋盘点,通过棋子是否在对角线或同一列判断是否能落子;
    递归的同时输出满足条件的方法;
    1.2解题详情
     eightQueen()函数判断是否能落子
     当queenCount == n 时,print()函数输出此种情况下落子情况。

#include 
#include 
#include //UNICODE工程-wide-character,用于双字节字符串
using namespace std;
#define n 8//皇后的个数
int a[n] = { 0 };
int total = 0;
//判断此列是否能满足条件
bool is_play(int row) {
    for (int i = 0; i < row; i++)
        if ((abs(i - row) == abs(a[i] - a[row])) || (a[i] == a[row]))//在对角线或者同一列
            return false;
    return true;
}
void print() {//打印各种解决放置方式
    cout << "第" << total << "种方法,列位置为:";
    for (int i = 0; i < n; i++)
        cout << a[i] << " ";
    cout << endl;
}
void eightQueen(int queenCount) {
    if (queenCount == n) {
        total++;
        print();
    }
    else
    {
        for (int i = 0; i < n; i++)
        {
            a[queenCount] = i;
            if (is_play(queenCount))
                eightQueen(queenCount + 1);
        }
    }
}
int main()
{   
    cout << "             行数:" ;
    for (int i = 0; i < n; i++)
        cout << i<<" ";
    cout << endl;
    eightQueen(0);
    return 0;
}

  1. 骑士游历问题
    2.1思路分析:
    定义二位数组作为棋盘,初始化为0;
    DFS算法遍历,判断是否已被访问或是否超界,若非法则回溯。
    所有点被访问时输出路径。
    2.2解题详情
    二维数组chess[8][8]作为棋盘
     dfs(int x, int y)函数根据走棋规则进行遍历;ifOut(int x, int y)函数判断是否出界;fVisited(int x, int y)函数判断是否被访问;
    当所有点被访问时输出结果
#include
#include
using namespace std;
int cal = 0; //统计走的顺序
//棋盘初始化为0做标记
int chess[8][8] =
{
    0, 0, 0, 0, 0, 0, 0, 0,
    0, 0, 0, 0, 0, 0, 0, 0,
    0, 0, 0, 0, 0, 0, 0, 0,
    0, 0, 0, 0, 0, 0, 0, 0,
    0, 0, 0, 0, 0, 0, 0, 0,
    0, 0, 0, 0, 0, 0, 0, 0,
    0, 0, 0, 0, 0, 0, 0, 0,
    0, 0, 0, 0, 0, 0, 0, 0
};
//判断是否出界
bool ifOut(int x, int y)  
{
    if (x >= 0 && x <= 7 && y >= 0 && y <= 7)
        return false;
    else
        return true;
}
//判断是否已经被访问
bool ifVisited(int x, int y) 
{
    if (chess[x][y] != 0)
        return true;
    else
        return false;
}
void dfs(int x, int y)
{
    if (cal == 64) //如果遍历完则退出棋盘一共64个位置
        return;
    if (!ifVisited(x, y) && !ifOut(x, y)) //如果没有被访问且没有出界 则访问
    {
        cal++;
        chess[x][y] = cal; //做标记
        dfs(x + 2, y + 1);	//骑士走法有八个方位,故八个 方位都遍历
        dfs(x - 2, y - 1);  //八个递归的顺序可以改,顺序不一样,结果不一样 
        dfs(x + 2, y - 1);
        dfs(x - 2, y + 1);
        dfs(x - 1, y - 2);
        dfs(x + 1, y - 2);
        dfs(x + 1, y + 2);
        dfs(x - 1, y + 2);
        return;
    }
    else  //出界了则退出return
        return;
}
int main()
{
    int x, y;
    cout << "请输入骑士初始的位置:";
    while (1)
    {
        cin >> x >> y;    //输入坐标
        if (x > 7 || x < 0 || y> 7 || y < 0)
            cout << "初始位置输入错误请重新输入" << endl;
        else
            break;
    }
    dfs(x, y);
    for (int i = 0; i < 8; i++)  //输出打印测试
    {
        for (int j = 0; j < 8; j++)
            cout << setw(2) << chess[i][j] << "  ";
        cout << endl;
    }
    return 0;
}

倒水问题:
3.1思路分析:
1.若先将小桶水装满:将小桶装满水倒入大桶;若大桶中水未满,则重复过程直至大桶中水满;若大桶中水满则倒掉大桶中的水每次倒水后判断大桶中水是否满足要求,满足题目条件则结束程序;若运行至小桶没有水,大桶满水则表示no solution,程序结束;
2.若先将大桶水装满:过程同上;
3.比较1和2中哪一种情况下步骤最少,输出最少的步骤。
3.2实例演示
例: 容器A:3 ;容器B:5 待装水体积:4
A容器装满水倒入B容器中,此时: A:0 ;B:3
 再将A容器装满水倒入B容器中,此时: A:1 ;B:5
B容器中水倒掉,A容器的水倒入B容器此时: A:0 ;B:1
再将A容器装满水倒入B容器中,此时: A:0 ;B:4
B容器中水的体积即为所求。将A,B容器互换重复以上操作。

#include
#include
#include
using namespace std;
//输出结果
void output(vector<int> a, vector<int> b, int L)
{
	vector<int>::iterator ita, itb, it;
	for (it = b.begin(); it < b.end(); it++)
	{
		if (*it == L)
			break;
	}
	cout << "A" << "\t" << "B" << endl;
//判断是后半部分长还是前半部分更长
	if (b.end() - it - 1 > it - b.begin() + 1)
	{
		ita = a.begin();
		itb = b.begin();
		while (itb <= it)
		{
			cout << *ita << "\t" << *itb << endl;
			ita++; itb++;
		}
	}
	else
	{
		for (it = b.end() - 1; it > b.begin(); it--)
		{
			if (*it == L)
				break;
		}
		ita = a.end() - 1;
		itb = b.end() - 1;
		while (itb >= it)
		{			cout << *ita << "\t" << *itb << endl;
			ita--; 
			itb--;
		}
	}
	cout << "B中装了" << L << "升水" << endl;
}
void Bucket_problem()
{
	int A, B, L;
	vector<int> A1, B1;//用两个向量保存两条数据,到时候容易比较长短和输出
	int flag = 0;
	cout << "分别输入容器A(小)和容器B(大)的容积:" << endl;
	cin >> A >> B;
	cout << "输入待装水的体积:" << endl;
	cin >> L;
	int M = max(A, B);
	int m = min(A, B);
	if (L > M)
	{
		cout << "No Solution" << endl;
		return;
	}
	if (L == m)
	{
		cout << "A" << "\t" << "B" << endl;
		cout << m << "\t" << "0" << endl;
		cout << "此时A中装了" << m << "升水" << endl;
		return;
	}
	if (L == M)
	{
		cout << "A" << "\t" << "B" << endl;
		cout << "0" << "\t" << M << endl;
		cout << "此时B中装了" << M << "升水" << endl;
		return;
	}
	int a = 0, b = 0;
	a = m;
	while (true)//制造一个循环
	{
		if (b == M)
		{
			b = 0;
			if (a == 0 && b == 0) break;//退出条件
			A1.push_back(a); B1.push_back(b);
			swap(a, b);
			A1.push_back(a); B1.push_back(b);
			a = m;
			continue;
		}
		A1.push_back(a); B1.push_back(b);
		b = b + a;
		if (b >= M)
		{
			a = b - M;
			b = M;
			A1.push_back(a); B1.push_back(b);
		}
		else
		{
			a = 0;
			A1.push_back(a); B1.push_back(b);
			a = m;
		}
	}
	output(A1, B1, L);
}
int main()
{
	Bucket_problem();
	return 0;
}

实验三、计算几何算法的实现

(1) 将讲义第三章第三节中的凸包代码上机运行并检验结果。
(2) 完成讲义第三章的课后习题,上机运行并检验结果。
(3) 思考:
判线段相交时,如果有个线段的端点在另一条线段上,注意可能与另一条线段上的
端点重合,思考这样的情况怎么办。
(4) 房间最短路问题:
给定一个内含阻碍墙的房间,求解出一条从起点到终点的最最短路径。房间的边界
固定在x=0,x=10,y=0 和y=10。起点和重点固定在(0,5)和(10,5)。房间里还有0 到8 个
墙,每个墙有两个门。输入给定的墙的个数,每个墙的x 位置和两个门的y 坐标区间,
输出最短路的长度。下图是个例子:
合肥工业大学 程序设计艺术与方法实验报告( STL 的熟悉与使用 搜索算法的实现 计算几何算法的实现 动态规划算法的实现)_第1张图片
第三章课后习题(判断是否为多边形,求多边形面积)
1.1思路分析:
判断能否构成多边形,即判断是否存在两直线相交:两直线互相跨立;或一条线段的一个端点在另一条线段上
.求多边形面积:取一顶点与其它顶点相连,相邻的边做向量积再除以2;也就是求每个三角形的面积。
1.2解题详情
用poi[i].x poi[i].y表示第i个点(x,y); line[i].head line[i].tail表示第i条边从点head到点tail
 inter(const line1& m, const line1& n)函数判断两直线是否相交
通过三角形两边矢量的叉乘求面积。

1.3源代码:
#include
#include
#include
#include
#include
#include
using namespace std;
const int maxn = 1100;
const double esp = 1e-10;
struct point {
    double x, y;
}poi[maxn];
struct line1 {
    point head, tail;
}line[maxn];
double tmin(double a, double b) {
    return a < b ? a : b;
}
double tmax(double a, double b) {
    return a > b ? a : b;
}
//判断是否相交
bool inter(const line1& m, const line1& n) {
    point a = m.head;
    point b = m.tail;
    point c = n.head;
    point d = n.tail;
    if (tmin(a.x, b.x) > tmax(c.x, d.x) ||
        tmin(a.y, b.y) > tmax(c.y, d.y) ||
        tmin(c.x, d.x) > tmax(a.x, b.x) ||
        tmin(c.y, d.y) > tmax(a.y, b.y))
        return 0;
    double h, i, j, k;
    h = (b.x - a.x) * (c.y - a.y) - (b.y - a.y) * (c.x - a.x);
    i = (b.x - a.x) * (d.y - a.y) - (b.y - a.y) * (d.x - a.x);
    j = (d.x - c.x) * (a.y - c.y) - (d.y - c.y) * (a.x - c.x);
    k = (d.x - c.x) * (b.y - c.y) - (d.y - c.y) * (b.x - c.x);
    return h * i <= esp && j * k <= esp;
}
int main() {
    int n;
    int cas = 1;
    while (scanf_s("%d", &n) != EOF) {
        if (n == 0)
            break;
        if (cas != 1)
            puts("");
        for (int i = 0; i < n; i++) {
            cin >> poi[i].x >> poi[i].y;
        }
        if (n < 3) {
            printf("Figure %d: Impossible\n", cas++);
            continue;
        }
        for (int i = 0; i < n; i++) {
            point u, v;
            if ((i == (n - 1))) {
                u.x = poi[i].x;
                u.y = poi[i].y;
                v.x = poi[0].x;
                v.y = poi[0].y;
            }
            else {
                u.x = poi[i].x;
                u.y = poi[i].y;
                v.x = poi[i + 1].x;
                v.y = poi[i + 1].y;
            }
            line[i].head = u;
            line[i].tail = v;
        }
        bool flag = false;
        bool tmp = false;
        for (int i = 0; i < n; i++) {
            for (int j = i + 2; j < n; j++) {
                if (i == 0 && (j == (n - 1)))
                    continue;
                tmp = inter(line[i], line[j]);
                if (tmp) {
                    flag = true;
                    break;
                }
            }
            if (flag)
                break;
        }
        if (flag) {
            printf("Figure %d: Impossible\n", cas++);
        }
        else {//求多边形面积
            double area = 0;
            double x1, x2, y1, y2, x0, y0;
            x0 = x1 = poi[0].x;
            y0 = y1 = poi[0].y;
            for (int i = 1; i <= n; i++)
            {
                if (i < n) {
                    x2 = poi[i].x;
                    y2 = poi[i].y;
                }
                else
                {
                    x2 = x0;
                    y2 = y0;
                }
                area += (y1 + y2) * (x2 - x1) * 0.5;
                x1 = x2;
                y1 = y2;
            }
            if (area < 0)
                area *= -1;
            printf("Figure %d: %.2f\n", cas++, area);
        }
    }
    return 0;
}

1.5思考:
若一线段端点在另一线段(除端点)上,则无法构成多边形;
若一线段端点与另一线段的端点重合,则可能构成多边形。但若三条线段端点重合则无法否成多边形。

房间最短路问题
2.1思路分析:
将起点,终点,每扇门的端点看成图的顶点。把这些点两两相连(若相连后线段与墙相交则不连)。即构成了图
问题转化成已知起点和终点的图求最短路问题。
2.2解题详情
 judge(point p1, point p2)函数判断两点之间是否有墙隔开,也就是判断两直线是否相交。
 floyd()函数求出图的最短路径。

2.3源代码:
#include
#include
#include
#include
#define eps 10e-8
#define inf 1<<29
using namespace std;
struct point
{
    double x, y;
};
int n;
double xx[22], yy[22][5];
point p[90];
double adj[90][90];
int psize;
double ff(double x)
{
    return x * x;
}
double dis(point p1, point p2)
{
    return sqrt(ff(p1.x - p2.x) + ff(p1.y - p2.y));
}
double cross(double x1, double y1, double x2, double y2, double x3, double y3)
{
    return (x2 - x1) * (y3 - y1) - (y2 - y1) * (x3 - x1);
}
bool judge(point p1, point p2)
{
    if (p1.x >= p2.x)return 0;
    int i = 0;
    while (xx[i] <= p1.x && i < n)i++;
    while (xx[i] < p2.x && i < n)
    {
        if (cross(p1.x, p1.y, p2.x, p2.y, xx[i], 0) * cross(p1.x, p1.y, p2.x, p2.y, xx[i], yy[i][1]) < 0
            || cross(p1.x, p1.y, p2.x, p2.y, xx[i], yy[i][2]) * cross(p1.x, p1.y, p2.x, p2.y, xx[i], yy[i][3]) < 0
            || cross(p1.x, p1.y, p2.x, p2.y, xx[i], yy[i][4]) * cross(p1.x, p1.y, p2.x, p2.y, xx[i], 10) < 0)
            return 0;
        i++;
    }
    return 1;
}
void floyd()
{
    int i, j, k;
    for (k = 0; k < psize; k++)
        for (i = 0; i < psize; i++)
            for (j = i + 1; j < psize; j++)
                if (i != k && j != k)
                    adj[i][j] = min(adj[i][j], adj[i][k] + adj[k][j]);
    printf("最短距离为:%.2f\n", adj[0][psize - 1]);
}
int main()
{
    int i, j;
    printf("输入墙的个数:\n");
    scanf_s("%d", &n);
    printf("分别输入墙的x坐标和门的y坐标\n");
        p[0].x = 0; p[0].y = 5; psize = 1;
       for (i = 0; i < n; i++)
        {
            scanf_s("%lf", &xx[i]);
            for (j = 1; j <= 4; j++)
            {
                p[psize].x = xx[i];
                scanf_s("%lf", &p[psize].y);
                yy[i][j] = p[psize].y;
                psize++;
            }
        }
        p[psize].x = 10; p[psize].y = 5;
        psize++;
        for (i = 0; i < psize; i++)
            for (j = 0; j < psize; j++)
                adj[i][j] = inf;
        for (i = 0; i < psize; i++)
            for (j = i + 1; j < psize; j++)
                if (judge(p[i], p[j]))
                    adj[i][j] = dis(p[i], p[j]);
        floyd();  
    return 0;
}

实验四、动态规划算法的实现

(1) 求两个字符串的最长公共子序列。
X 的一个子序列是相应于X 下标序列{1, 2, …, m}的一个子序列,求解两个序列的所有子序列中长度最大的,例如输入:pear, peach 输出:pea。
(2) 给定两个字符串a 和b,现将串a 通过变换变为串b,可用的操作为,删除串a 中的一个字符;在串a 的某个位置插入一个元素;将串a 中的某个字母换为另一个字母。对于任意的串a 和串b,输出最少多少次能够将串变为串b。
思考:输出变换的步骤。
(3) 输入一个矩阵,计算所有的子矩阵中和的最大值。
例如,输入
0 -2 -7 0
9 2 -6 2
-4 1 -4 1
-1 8 0 -2
输出为:15
思考:当矩阵很大时,比如100*100 的矩阵,你的程序还能够很快的得出结果吗,如果不能,请思考如何用动态规划的思想解决。

合肥工业大学 程序设计艺术与方法实验报告( STL 的熟悉与使用 搜索算法的实现 计算几何算法的实现 动态规划算法的实现)_第2张图片
合肥工业大学 程序设计艺术与方法实验报告( STL 的熟悉与使用 搜索算法的实现 计算几何算法的实现 动态规划算法的实现)_第3张图片
合肥工业大学 程序设计艺术与方法实验报告( STL 的熟悉与使用 搜索算法的实现 计算几何算法的实现 动态规划算法的实现)_第4张图片

1.3源代码
#include 
#include 
#define MAXLEN 100
using namespace std;
void LCS(char* x, char* y, int m, int n, int c[][MAXLEN], int b[][MAXLEN])
{
    int i, j;

    for (i = 0; i <= m; i++)
        c[i][0] = 0;
    for (j = 1; j <= n; j++)
        c[0][j] = 0;
    for (i = 1; i <= m; i++)
    {
        for (j = 1; j <= n; j++)
        {
            if (x[i - 1] == y[j - 1])
            {
                c[i][j] = c[i - 1][j - 1] + 1;
                b[i][j] = 0;
            }
            else if (c[i - 1][j] >= c[i][j - 1])
            {
                c[i][j] = c[i - 1][j];
                b[i][j] = 1;
            }
            else
            {
                c[i][j] = c[i][j - 1];
                b[i][j] = -1;
            }
        }
    }
}

void Print(int b[][MAXLEN], char* x, int i, int j)
{
    if (i == 0 || j == 0)
        return;
    if (b[i][j] == 0)
    {
        Print(b, x, i - 1, j - 1);
        printf("%c ", x[i - 1]);
    }
    else if (b[i][j] == 1)
        Print(b, x, i - 1, j);
    else
        Print(b, x, i, j - 1);
}
int main(int argc, char** argv)
{
    char x[MAXLEN];
    char y[MAXLEN];
    int b[MAXLEN][MAXLEN];
    int c[MAXLEN][MAXLEN];
    int m, n;
    cout << "请输入第一个字符串:" << endl;
    scanf_s("%s", x, MAXLEN);//scanf_s要求在输入char或字符串数组时,添加最大长度作为参数,这样可以显式地防止输入越界。
    cout << "\n请输入第二个字符串:" << endl;
    scanf_s("%s", y, MAXLEN);
    m = strlen(x);
    n = strlen(y);
    LCS(x, y, m, n, c, b);
    cout << "两个字符串的最大公共子序列是:";
    Print(b, x, m, n);
    return 0;
}

  1. 串A变串B
    2.1思路分析
    定义一个二维数组D[i][j] 存储每一个对应的字符串A的前i个元素与字符串B的前j个元素的最小编辑距离D[i][j].
    规律如下:D[i][j]=min(min(D[i-1][j]+1,D[i][j-1]+1),(A[j-1]==B[i-1]?D[i-1][j-1]: D[i-1][j-1]+1)); 从D[0][0]开始一直操作到了D [i][j]位置,其中删除操作肯定是str1比str2长,插入操作str1比str2短,我们所要做的是对D [i-1][j] 、D [i][j-1]、D [i-1][j-1]存的数进行比较,其中最小的就是当前str1和str2的编辑距离。
 2.2源程序
#include 
#include 
#include 
using namespace std;

int minDist(string A, string B)
{
    int aLen = A.length();
    int bLen = B.length();
    int D[bLen + 1][aLen + 1];
    for (int j = 0; j <= aLen; j++) {
        //初始化第一行
        D[0][j] = j;
    }
    for (int i = 0; i <= bLen; i++) {
        //初始化第一列
        D[i][0] = i;
    }

    for (int i = 1; i <= bLen; i++) {
        for (int j = 1; j <= aLen; j++) {
            //初始化表格
            D[i][j] = min(min(D[i - 1][j] + 1, D[i][j - 1] + 1), (A[j - 1] == B[i - 1] ? D[i - 1][j - 1] : D[i - 1][j - 1] + 1));
        }
    }

    return D[bLen][aLen];
}

int main()
{
    string a, b;
    cout << "请输入字符串A :" << endl;
    cin >> a;
    cout << "\n请输入字字符串B :" << endl;
    cin >> b;
    cout << "\n最少次数:"<<minDist(a, b)<<endl;
    return 0;
}

3.子矩阵最大和
3.1思路分析
将矩阵存入二维数组中,将二维数组第 i 行到第 j 行相同列的元素加起来,然后再当作一维数组来求解;
用b[i][j]记录第j列,0~i行的元素之和。那么当i>0时,要想得到第k列,从第i行到第j行的元素之和则通过计算 b[j][k]-b[i-1][k] 得到。当i==0时直接就是b[j][k]。
通过上述方法将二维转化为一维数组。再对这个一维数组用算法求子数组元素之和的最大值。不断的更新最大值,便是最终的结果。

#include 
#include 
using namespace std;
int main()
{
    int a, b;
    cout << "请输入矩阵的行数和列数:" << endl;
    cin >> a >> b;
    int d[a][b];
    cout << "请输入矩阵:" << endl;
    for(int i = 0; i < a; i++){
        for(int j = 0; j < b; j++){
            cin >> d[i][j];
        }
    }
    int sum, tmp;
    int c[b];
    sum = -999;
    for(int i = 0; i < a; i++){
        memset(c, 0 ,sizeof(c));
        for(int j = i; j < a; j++){
            tmp = 0;
            for(int k = 0; k < b; k++){
                c[k] += d[j][k];
                if(tmp >= 0)
                    tmp += c[k];
                else
                    tmp = c[k];
                if(sum < tmp)
                    sum = tmp;
            }
        }
    }
    cout << "矩阵最大的子矩阵和为:" << sum;
}

这里有完整的实验报告
CS·恰烂钱·恶心·DN 居然会根据下载量自动涨积分!!!
而且更改后又自动涨积分
祝~早日倒闭
资源连接点这里
既来之~
则赞之~

你可能感兴趣的:(合肥工业大学 程序设计艺术与方法实验报告( STL 的熟悉与使用 搜索算法的实现 计算几何算法的实现 动态规划算法的实现))