华北电力大学(保定)2021级软件工程专业算法分析与设计实验

本文章仅转载他人代码,非本人实验所用!如有侵权,请联系我,我会删除文章!

请同学们自主思考,不要复制粘贴网上代码,不当使用造成的后果本人概不负责!

实验任务书

 

   本文章是我整合了两个人的实验所完成,其中部分代码是他们从网上粘贴然后自己进行修改,为了降重把一些变量名和函数名改的非常反人类,如有雷同,不是巧合。

实验一 归并排序

2024.2.2补充:copy那块多打了几个大括号,缩进有点问题,但是不影响执行。

#include<iostream>
#include<vector>
#include<ctime>
#include <random>
#include<algorithm>
using namespace std;
float a[1000000]{ };//生成一百万个随机数
float c[1000000]{};
float d[1000000]{};
template <class T>
    bool operator <(const T& a, const T& b) {
    return (a.data < b.data);
    }
template <class T>
void merge_sort(T a[], int l, int r)
{
    if (l == r) 
        return;
    int mid = l + r >> 1;
    merge_sort(a, l, mid), merge_sort(a, mid + 1, r);
    int i = l, j = mid + 1, k = 0;
    while (i <= mid && j <= r) {
        if (a[i] <= a[j]) {
            c[k++] = a[i++];
        }
        else {
            c[k++] = a[j++];
        }
    }
    while (i <= mid) c[k++] = a[i++]; {
        while (j <= r) c[k++] = a[j++]; {
            for (int i = l, j = 0; i <= r; i++, j++) {//Copy
                a[i] = c[j];
            }
        }}
}
int main()
{
    time_t begin1, end1,begin2,end2;

    uniform_real_distribution<double> u(-20030905, 20030905);
    default_random_engine e(time(NULL));

    ios_base::fmtflags orig = cout.setf(ios_base::fixed, ios_base::floatfield);//阻止科学计数法
    std::streamsize prec = cout.precision(5);//控制位数
    //归并排序开始计时
  
    for (int i = 0; i < 1000000; i++) {
        a[i] = u(e);
        d[i] = a[i];
    } 
    begin1 = clock();
    merge_sort(a, 0, 999999);
    /*for (int i = 0; i < 100; i++) {
        printf("%8f ", a[i]);
    }*/
    end1 = clock();
    double time1 = (double)(end1 - begin1) / CLOCKS_PER_SEC;
    cout << endl;
    cout <<"归并排序的时间为 " << time1<<"s";

    begin2 = clock();
    sort(d, d + 1000001);
    end2 = clock();
    double time2 = (double)(end2 - begin2) / CLOCKS_PER_SEC;
    cout << endl;
    cout << "标准库排序的时间为 " << time2 << "s" << endl;
}

其实没用到vector,当时是考虑输入的数据类型可能不是数字才设置的,mid右移一位是因为我当时学的那篇文章就用的位运算,我索性直接复制过来了,其实就是除以二。

2024.2.3补充:加一个非递归实现归并排序,排序之归并排序-CSDN博客,f是待排数组,g是存放临时数据的数组。

void no_merge_sort(float f[], int n) {
    int gap = 1;
    while (gap < n) {
        for (int i = 0; i < n; i += gap * 2) {
            int begin1 = i;
            int end1 = i + gap-1;
            int begin2 = end1 + 1;
            int end2 = i + 2 * gap - 1;
            if (end1 >= n || begin2 >= n) {
                break;
            }
            if (end2 >= n) {
                end2 = n - 1;
            }
            int j = begin1;
            while ((begin1 <= end1) && (begin2 <= end2))
            {
                if (f[begin1] < f[begin2])
                {
                    g[j++] = f[begin1++];
                }
                else
                {
                    g[j++] = f[begin2++];
                }
            }
            while (begin1 <= end1)
            {
                g[j++] = f[begin1++];
            }
            while (begin2 <= end2)
            {
                g[j++] = f[begin2++];
            }
           
        }
        gap = gap * 2;
    }
    for (int k = 0; k < 1000000; k++) {
        f[k] = g[k];
    }
}

实验二 哈夫曼编码

#include <iostream>
#include <fstream>
#include <string>
#include <algorithm>
#include <queue>
#include <stack>
using namespace std;
struct THuffman {
	char ch;
	long weight;
	int l, r;
	int p;
	string code;
	int idx;//记录索引,便于建立树
	THuffman() :l(-1), r(-1), p(-1), ch('/0'), weight(0), idx(-1) {}
};
struct temp_node {
	char ch = '0';
	long weight = 0;
};
bool operator >(const THuffman& a, const THuffman& b) {
	return(a.weight > b.weight);
}
bool operator <(const THuffman& a, const THuffman& b) {
	return(a.weight < b.weight);
}

struct Huffman {
	string hfilename;
	Huffman(string filename) {
		hfilename = filename;
	}
	void OutputCode() {
		unsigned char temp_char;
		long file_len = 0;//统计文件长度
		int kind = 0;
		temp_node filechar[256];//此数组装载文件中字符频度及字符本身
		for (int i = 0; i < 256; i++) {
			filechar[i].weight = 0;
			filechar[i].ch = (unsigned char)i;
		}
		ifstream infile;
		infile.open(hfilename);
		if (!infile.is_open()) {
			cout << "打开文件失败";
			return ;
		}
		infile.read((char*)&temp_char, sizeof(unsigned char));
		while (!infile.eof()) {//这么写可以防止文件里什么也没有导致filechar中数据出错
			filechar[temp_char].weight++;
			file_len++;
			infile.read((char*)&temp_char, sizeof(unsigned char));
		}
		infile.close();
		//接下来排序,以便获得文件中字符数目
		sort(filechar, filechar + 257, [](temp_node a, temp_node b) {
			return a.weight > b.weight; });

		for (int i = 0; i < 256; i++) {
			if (filechar[i].weight != 0) {
				kind++;
			}
		}
		//文件信息已扫描完毕,可以开始进行编码了
		THuffman* t = new THuffman[2 * kind - 1];
		priority_queue<THuffman, vector<THuffman>, greater<THuffman>>PQ;
		for (int i = 0; i < kind; i++) {
			t[i].idx = i;
			t[i].weight = filechar[i].weight;
			t[i].ch = filechar[i].ch;
			PQ.push(t[i]);
		}
		int k = kind;
		for (int i = 0; i <= kind - 2; i++) {
			THuffman l = PQ.top();
			PQ.pop();
			THuffman r = PQ.top();
			PQ.pop();
			t[k].idx = k;
			t[k].weight = l.weight + r.weight;
			t[k].l = l.idx;
			t[k].r = r.idx;
			t[l.idx].p = k;
			t[r.idx].p = k;
			PQ.push(t[k]);
			k++;
		}
		//树已经得到,接下来输出各编码
		priority_queue<THuffman, vector<THuffman>>output;
		for (int i = 0; i < kind; i++) {
			output.push(t[i]);
		}
		for (int i = 0; i < kind; i++) {
			cout << output.top().ch << ":" << output.top().weight << "次,编码为";
			THuffman p = output.top();
			THuffman pp = t[p.p];
			stack<int>code;
			while (1) {
				if (p.idx == pp.l) {
					code.push(0);

				}
				else if (p.idx == pp.r) {
					code.push(1);
				}

				p = pp;
				if (p.p == -1) {
					break;
				}
				pp = t[p.p];
			}
			int temp = code.size();
			for (int j = 0; j < temp; j++) {
				cout << code.top();
				//t[output.top().idx].code += code.top();
				code.pop();
			}
			cout << endl;
			output.pop();
		}
		delete[]t;

	}
};
int main() {
	Huffman hm("test.txt");
	cout << "打开的文件名为:test.txt" << endl;
	hm.OutputCode();
}

运行结果类似这样

  待打开的文件放在visual对应的文件夹下面运行,其实这个代码打不开doc文件,但是txt文件自己把后缀改成doc之后就可以,我也不知道为什么;老师建议不要用逐字符的方式读入,可以改成一次读入若干字符提高效率,这里没改,请读者自行发挥吧。

实验三  矩阵链乘

#include <iostream>
#include <string>
using namespace std;
struct Sheet {
    long m;
    int k;
};
struct matrix {
    int right_right_bak = 0;
    int left_left_bak = 0;
    int right_left_bak = 0;
    string ch;
};
int p[] = { 60,2,1,3,4,5,2};
int n = 6;
Sheet** A = new Sheet * [n + 1];
void bracket2(int left, int right, matrix* a)
{
    if (left == right)
    {
        cout << a[left].ch;
    }
    else
    {
        cout<<"(";
        bracket2(left, A[left][right].k,a);
        bracket2(A[left][right].k + 1, right,a);
        cout<<")";
    }
}
int main()
{
    for (int i = 0; i <= n; i++) {
        A[i] = new Sheet  [n + 1]; 
        A[0][i].m = 0;
    }   
    for (int i = 0; i <= n; i++) {
        A[i][i].m = 0;
        A[i][i].k = 0;
    }
    A[1][2].m = p[0] * p[1] * p[2];
    for (int r = 2; r <= n; r++) {
        for (int i = 1; i + r - 1 <= n; i++) {
            int j = r + i - 1;
            long mm = A[i + 1][j].m + p[i - 1] * p[i] * p[j];
            int kk = i;
            for (int k = i + 1; k < j; k++) {
                long tempM = A[i][k].m + A[k + 1][j].m + p[i - 1] * p[k] * p[j];
                if (tempM < mm) {
                    mm = tempM;
                    kk = k;
                }
 
            }   
            A[i][j].m = mm;
            A[i][j].k = kk;
        }
    }
    matrix a[27];
    a[0].ch = "NULL";
    a[1].ch = "A";
    a[2].ch = "B";
    a[3].ch = "C";
    a[4].ch = "D";
    a[5].ch = "E";
    a[6].ch = "F";
    a[7].ch = "G";
    a[8].ch = "H";
    a[9].ch = "I";
    a[10].ch = "J";
    a[11].ch = "K";
    a[12].ch = "L";
    a[13].ch = "M"; 
    a[14].ch = "N";
    a[15].ch = "O";
    a[16].ch = "P";
    a[17].ch = "Q";
    a[18].ch = "R";
    a[19].ch = "S";
    a[20].ch = "T";
    a[21].ch = "U"; 
    a[22].ch = "V";
    a[23].ch = "W";
    a[24].ch = "X";
    a[25].ch = "Y";
    a[26].ch = "Z";
    cout<<"最小乘法次数为 " << A[1][n].m << endl;

    cout << "加括号方式为";
    bracket2(1, n, a);
    for (int i = 0; i <= n; i++) {
        delete []A[i];
    }
    delete[]A;
}

  其实我自己花好久写了一个加括号方式,但是运行结果太丑了,无奈删掉( Ĭ ^ Ĭ )。

  没有输入,自己修改矩阵数量和行列数,行列数数组第0个元素是第一个矩阵的行,第i个元素是第i个矩阵的列数。

  结果大概这样

 实验四 n皇后问题

#include <iostream>
#include <vector>
using namespace std;
struct Queen {
	int N;
	int m_sum;//解数
	Queen() {};
	~Queen() {};
	vector<int> row_set;//每一行皇后的置放位置情况
	vector<int> col_set;//每一列只能有一个皇后,记录每一列的状态
	vector<vector<int>> solution;//存储可行方案
	int curRow = 0;//当前待放皇后的行数
	bool check(int curRow, int col) {
		for (int i = curRow - 1; i >= 0; i--) {
			if (curRow - i == abs(col - row_set[i])) {
				return false;
			}
		}
		return true;
	}
	void Slove(int curRow) {
		if (curRow >= N) {//递归出口
			solution.push_back(row_set);
			return;
		}
		for (int i = 0; i < N; ++i) {
			if (col_set[i]) {
				continue;
			}
			if (check(curRow, i)) {
				col_set[i] = true;
				row_set.push_back(i);
				Slove(curRow + 1);
				col_set[i] = false;
				row_set.pop_back();
			}
		}
	}
	void IniQueen(int n) {//初始化,并计算该n值下的各种解
		N = n;
		for (int i = 0; i < N; i++) {
			col_set.push_back(0);
		}
		Slove(0);
	}
	void Print_All() {//输出n皇后问题的所有解向量
		int f = 1;
		cout << N << "皇后问题,方案如下:" << endl<<endl;
		for (vector<vector<int>>::iterator it = solution.begin(); it != solution.end(); it++) {
			cout << "第" << f++ << "种放置方案, 解向量为 " << endl;
			for (int i = 0; i < it->size(); i++) {
				cout << (*it)[i] + 1 << "  ";
			}
			cout << endl;
		}
		return;
	}
	int Get_Key_Sum() {//返回解数
		m_sum = solution.size();
		return m_sum;
	}
	void Print_Firstkey() {//输出第一个解向量
		cout << "(";
			for (int i = 0; i < solution[0].size()-1; i++) {
				cout << solution[0][i]+1 << " ,";
			}
			cout << solution[0][solution[0].size() - 1]+1;
			cout << ")";
		return;
	}
	void Print_Sheet() {//输出表格
		char h_line = '-';
		char v_line = '|';
		for (int i = 0; i < 67; i++) {
			cout << h_line;
		}
		cout << endl;
			cout << " 皇后数 ";
			cout << v_line;
			cout << "   解数   ";
			cout << v_line;
			cout << "                   第一个解                   ";
			cout << v_line;
			cout << endl;
			for (int i = 4; i <= N; i++) {
				for (int i = 0; i < 67; i++) {
					cout << h_line;
				}
				cout << endl;
				Queen temp;
				temp.IniQueen(i);
				printf("%5d", i);
				cout << "   ";
				cout << v_line;
				printf("%6d", temp.Get_Key_Sum());
				cout << "    ";
				cout << v_line;
				temp.Print_Firstkey();
				cout << endl;
			}
	}
};
int main() {
	Queen que;
	que.IniQueen(6);
	que.Print_Sheet();
	que.Print_All();
}

  运行时自己修改初始化时的参数,皇后数尽量不要超过12,要不然会很慢。准备了好几个输出用的函数,用哪个调哪个。

实验五  贪心背包

#include <iostream>
#include <vector>
#include <algorithm>
#include <random>
using namespace std;
/*实验要求为贪心算法,本题为部分背包问题,每种物品只有一个,但是可以取部分,
考虑到本实验要求std::sort,所以没有使用优先队列,而是使用vector*/
struct goods {
	float value = 0.0;
	float weight = 0.0;
	float rate = 0.0;
	bool pick = false;
	int number = 0;
	goods() {};
	goods(float v, float w) {
		value = v;
		weight = w;
		rate = value / weight;
	}
	void cum_rate() {
		rate = value / weight;
	}
};
bool cmp_rate(const goods a, const goods b) {
	return (a.rate > b.rate);
}
bool cmp_number(const goods a, const goods b) {
	return (a.number < b.number);
}
struct Greedy_partbag {
	int n;//待选物品数量
	float c=0.0;//背包容量
	float cv=0.0;//已经装入的价值
	float cw=0.0;//已经装入的重量
	vector<goods>goods_set;//所有物品的状态表
	Greedy_partbag() {};
	~Greedy_partbag() {};
	void Greedy_partbag_Solution() {//读取输入并解决问题
		cin >> n;
		cin >> c;
		uniform_real_distribution<float> u(0, 100);
		default_random_engine e(time(0));
		for (int i = 0; i < n; i++) {//读取输入
			goods temp;
			/*cin >> temp.value;
			cin >> temp.weight;*/
			//这里采用随机数的方法作为价值和重量
			temp.value = u(e);
			temp.weight = u(e);
			temp.rate = temp.value / temp.weight;
			temp.number = i + 1;
			goods_set.push_back(temp);
		}
		//接下来对物品性价比进行排序
		sort(goods_set.begin(), goods_set.end(), cmp_rate);
		for (int i = 0; i < n; i++) {//装入物品
			if (goods_set[i].weight < (c - cw)) {
				goods_set[i].pick = true;
				cv = cv + goods_set[i].value;
				cw = cw + goods_set[i].weight;
				continue;
			}
			if (goods_set[i].weight == (c - cw)) {
				goods_set[i].pick = true;
				cv = cv + goods_set[i].value;
				cw = cw + goods_set[i].weight;
				break;
			}
			if (goods_set[i].weight > (c - cw)) {
				goods_set[i].pick = true;
				cv = cv + goods_set[i].value*((c-cw)/goods_set[i].weight);
				cw = c;
				break;
			}
		}
		//重新排序,以便于输出物品列表
		sort(goods_set.begin(), goods_set.end(), cmp_number);
	}
	void Print_Sheet() {
		for (int i = 1; i <= goods_set.size() + 1; i++) {
			cout << "--------" ;
		}
		cout << "-";
		cout << endl;

		cout << "物品编号" << "|";
		for(int i=1;i<=goods_set.size();i++){
			printf("%4d", i);
			cout << "   |";
		}
		cout << endl;

		for (int i = 1; i <= goods_set.size() + 1; i++) {
			cout << "--------";
		}
		cout << "-" << endl;

		cout << "  重量  "<<"|";
		for (int i = 0; i < goods_set.size(); i++) {
			printf("%5.1f", goods_set[i].weight);
			cout << "  |";
		}
		cout << endl;

		for (int i = 1; i <= goods_set.size() + 1; i++) {
			cout << "--------";
		}
		cout << "-" << endl;

		cout << "  价值  " << "|";
		for (int i = 0; i < goods_set.size(); i++) {
			printf("%5.1f", goods_set[i].value);
			cout << "  |";
		}

		cout << endl;
		for (int i = 1; i <= goods_set.size() + 1; i++) {
			cout << "--------";
		}
		cout << "-" << endl;

		cout << "选中状态" << "|";
		for (int i = 0; i < goods_set.size(); i++) {
			printf("%4d", goods_set[i].pick);
			cout << "   |";
		}
		cout << endl;

		for (int i = 1; i <= goods_set.size() + 1; i++) {
			cout << "--------";
		}
		cout << "-" << endl;
		cout << " 性价比 " << "|";
		for (int i = 0; i < goods_set.size(); i++) {
			printf("%5.2f", goods_set[i].rate);
			cout << "  |";
		}
		cout << endl;

		for (int i = 1; i <= goods_set.size() + 1; i++) {
			cout << "--------";
		}
		cout << "-" << endl;
	}
	void Print_Result() {
		printf("最佳价值为 %.2f",cv);
	}
};

int main() {
	Greedy_partbag bag;
	cout << "输入物品数量和背包容量:" << endl;;
	bag.Greedy_partbag_Solution();
	bag.Print_Sheet();
	bag.Print_Result();

}

  实验六  0-1背包

  回溯法

#include <iostream>
#include <vector>
#include <random>
using namespace std;
//深搜背包
struct goods {
	float value = 0.0;
	float weight = 0.0;
	int number = 0;
	bool pick = false;
};
struct dfs_bag {
	int n = 0;
	float c = 0.0;
	float cv = 0.0;
	float cw = 0.0;
	float max_v = 0.0;
	int* best;
	vector<goods>goods_set;
	dfs_bag() {};
	~dfs_bag() {
		delete[]best;
	};
	void input() {
		cin >> n;
		cin >> c;
		best = new int [n+1];
		for (int i = 0; i <= n; i++)
			best[i] = 0;
		uniform_real_distribution<float> u(0, 100);
		default_random_engine e(time(0));
		goods scrap;//第一个元素无效,为了对齐编号加的
		goods_set.push_back(scrap);
		for (int i = 0; i < n; i++) {//读取输入
			goods temp;
			/*cin >> temp.value;
			cin >> temp.weight;*/
			temp.value = u(e);
			temp.weight = u(e);
			temp.number = i + 1;
			goods_set.push_back(temp);
		}
	}
	void dfs(int k) {
		if (k > n) {
			if (cv > max_v) {
				max_v = cv;
				for (int i = 1; i <= n; i++) {
					best[i] = goods_set[i].pick;
				}
				return;
			}
			return;
		}
			for (int i = 1; i >= 0; i--) {//轮流赋1或0表示选中与否
				goods_set[k].pick = i;
				if (cw + goods_set[k].pick * goods_set[k].weight <= c) {
					cw = cw + goods_set[k].pick * goods_set[k].weight;
					cv = cv + goods_set[k].pick * goods_set[k].value;
					dfs(k + 1);
					cw = cw - goods_set[k].pick * goods_set[k].weight;
					cv = cv - goods_set[k].pick * goods_set[k].value;//解已经存入数组,把cv和cw还原便于其他递归调用
				}
			}
	}
	void Print_Sheet() {
		for (int i = 1; i < goods_set.size() + 1; i++) {
			cout << "--------";
		}
		cout << "-";
		cout << endl;

		cout << "物品编号" << "|";
		for (int i = 1; i < goods_set.size(); i++) {
			printf("%4d", i);
			cout << "   |";
		}
		cout << endl;

		for (int i = 1; i < goods_set.size() + 1; i++) {
			cout << "--------";
		}
		cout << "-" << endl;

		cout << "  重量  " << "|";
		for (int i = 1; i < goods_set.size(); i++) {
			printf("%5.1f", goods_set[i].weight);
			cout << "  |";
		}
		cout << endl;

		for (int i = 1; i <= goods_set.size(); i++) {
			cout << "--------";
		}
		cout << "-" << endl;

		cout << "  价值  " << "|";
		for (int i = 1; i < goods_set.size(); i++) {
			printf("%5.1f", goods_set[i].value);
			cout << "  |";
		}

		cout << endl;
		for (int i = 1; i <= goods_set.size(); i++) {
			cout << "--------";
		}
		cout << "-" << endl;

		cout << "选中状态" << "|";
		for (int i = 1; i < goods_set.size(); i++) {
			printf("%4d", best[i]);
			cout << "   |";
		}
		cout << endl;
		for (int i = 1; i < goods_set.size() + 1; i++) {
			cout << "--------";
		}
		cout << "-" << endl;
	}
	void Print_Result() {
		printf("最佳价值为 %.2f", max_v);
	}
};

int main() {
	dfs_bag a;
	a.input();
	a.dfs(1);
	a.Print_Sheet();
	a.Print_Result();
}

  输入为 物品数量和背包容量。

  分支限界

#include <iostream>
#include <vector>
#include<algorithm>
#include<queue>
#include <random>
using namespace std;
struct goods
{
    int number;
    float weight;
    float value;
    float d;
};
struct Big_Priority_Tree
{
    Big_Priority_Tree* parent;
    int lchild;
    float upvalue;
    float value;
    float weight;
    int layer;
};
struct cmp
{
    bool operator()(Big_Priority_Tree*& a, Big_Priority_Tree*& b) const
    {
        return a->upvalue < b->upvalue;
    }
};
bool compare(const goods a, const goods b)
{
    return a.d >= b.d;
}
int n;
float c;
float cw;
float cv;
float max_v;
vector<goods> goods_set;
vector <goods>origin_goods_set;
int bestx[100];
void input()
{
    cin >> n >> c;
    uniform_real_distribution<float> u(0, 100);
    default_random_engine e(time(0));
    for (int i = 1; i <= n; i++)
    {
        goods temp;
        temp.value = u(e);
        temp.weight = u(e);
        temp.number = i;
        temp.d = 1.0 * temp.value / temp.weight;
        goods_set.push_back(temp);
    }
    origin_goods_set = goods_set;

    sort(goods_set.begin(), goods_set.end(), compare);
}
float Bound(int i)
{
    float tmp_cleft = c - cw;
    float tmp_cv = cv;
    while (i<=n&&tmp_cleft >= goods_set[i-1].weight )
    {
        tmp_cleft -= goods_set[i-1].weight;
        tmp_cv += goods_set[i-1].value;
        i++;
    }
    if (i <= n)
    {
        tmp_cv += tmp_cleft * goods_set[i-1].d;
    }
    return tmp_cv;
}
void Push_Alive_Node(priority_queue<Big_Priority_Tree*, vector<Big_Priority_Tree*>, cmp>& q, Big_Priority_Tree* E, float up, float wt, float curp, int i, int ch)
{
    Big_Priority_Tree* p = new Big_Priority_Tree;
    p->parent = E;
    p->lchild = ch;
    p->weight = wt;
    p->upvalue = up;
    p->value = curp;
    p->layer = i + 1;
    q.push(p);
}
void Bag()
{
    priority_queue<Big_Priority_Tree*, vector<Big_Priority_Tree*>, cmp > q; 
    Big_Priority_Tree* E = NULL;
    cw = cv = max_v = 0;
    int i = 1;
    float up = Bound(1);
    while (i != n + 1)
    {
        float wt = cw + goods_set[i-1].weight;
        if (wt <= c)
        {
            if (max_v < cv + goods_set[i-1].value)
                max_v = cv + goods_set[i-1].value;
            Push_Alive_Node(q, E, up, cw + goods_set[i-1].weight, cv + goods_set[i-1].value, i, 1);
        }
        up = Bound(i + 1);
        if (up >= max_v) 
        {
            Push_Alive_Node(q, E, up, cw, cv, i, 0);
        }
        E = q.top();
        q.pop();
        cw = E->weight;
        cv = E->value;
        up = E->upvalue;
        i = E->layer;
    }
    for (int i = 0; i<n; i++)
    {
        bestx[goods_set[E->layer - 2].number] = E->lchild;
        E = E->parent;
    }
}
void Print_Sheet() {
    for (int i = 0; i < goods_set.size() + 1; i++) {
        cout << "--------";
    }
    cout << "-";
    cout << endl;

    cout << "物品编号" << "|";
    for (int i = 1; i <= goods_set.size(); i++) {
        printf("%4d", i);
        cout << "   |";
    }
    cout << endl;

    for (int i = 0; i < goods_set.size() + 1; i++) {
        cout << "--------";
    }
    cout << "-" << endl;

    cout << "  重量  " << "|";
    for (int i = 0; i < goods_set.size(); i++) {
        printf("%5.1f", origin_goods_set[i].weight);
        cout << "  |";
    }
    cout << endl;

    for (int i = 0; i <= goods_set.size(); i++) {
        cout << "--------";
    }
    cout << "-" << endl;

    cout << "  价值  " << "|";
    for (int i = 0; i < goods_set.size(); i++) {
        printf("%5.1f", origin_goods_set[i].value);
        cout << "  |";
    }

    cout << endl;
    for (int i = 0; i <= goods_set.size(); i++) {
        cout << "--------";
    }
    cout << "-" << endl;

    cout << "选中状态" << "|";
    for (int i = 1; i <= goods_set.size(); i++) {
        printf("%4d", bestx[i]);
        cout << "   |";
    }
    cout << endl;
    for (int i = 0; i < goods_set.size() + 1; i++) {
        cout << "--------";
    }
    cout << "-" << endl;
}
void Print_Max_v()
{
    printf("最优装入量为 %.2f", max_v);
    cout << endl;
}
int main()
{
    input();
    Bag();
    Print_Max_v();
    Print_Sheet();
}

  代码是网上搜的,建议大家也去搜索然后认真学习一下,分支限界并不是单纯的广搜,而是使用优先队列和限界函数进行辅助,

参考了选修课《人工智能导论》的内容,对原始的广度优先搜索进行改良,设
置了上界函数,上界函数类似贪心法的部分背包问题,首先按性价比对各个物品进行排序,
从队首进行处理,使用 Bound 函数为结点计算上界,拿取(左)时上界继承父节点上界,对
重量进行判断,超过容量则一定不能拿,当可以拿取时将其加入队列,认为其可扩展,不拿
取(右)时,对 bestp 和 up 进行比较,bestp 表示已搜索到的方案中最优价值,up 则是走
到这一步之后的上界,连上界都小于 bestp 了,那么也没有必要搜索这一条路径了,直接剪
掉,一直搜索,一直到叶结点则结束,得到最优解。在登记最优解时从叶结点向上爬升,左
1 右 0,直至根节点。

实验七 第K小问题

原地分区

#include <iostream>
#include<random>
#include <algorithm>
//原地分区法第k小问题
using namespace std;
inline void swap(int& a, int& b) {
    int temp = a;
    a = b;
    b = temp;
}
int partition(int a[], int l, int r) {
    int x = a[l];
    int i = l;
    for (int j = l + 1; j <= r; j++) {
        if (a[j] < x) {
            i++;
            swap(a[i], a[j]);
        }
    }
    swap(a[i], a[l]);
    return i;
}
int kth_element_partition(int* a, int l, int r, int k) {
    if (l == r) {
        return a[l];
    }
    int m = partition(a, l, r);
    int kk = m - l + 1;
    if (k == kk) {
        return a[m];
    }
    if (k < kk) {
        return kth_element_partition(a, l, m - 1, k);
    }
    else return kth_element_partition(a, m + 1, r, k - kk);
}

int main()
{
    int n = 0;
    int k = 0;
    int a[10]{};
    uniform_real_distribution<float> u(0, 100);
    default_random_engine e(time(NULL));
    for (int i = 0; i < sizeof(a) / sizeof(int); i++) {
        a[i] = (int)u(e);
    }
    cin >>k;   
    for (int i = 0; i < sizeof(a) / sizeof(int); i++) {
        cout << a[i]<<" "; 
    }
    cout << endl;
    cout << kth_element_partition(a, 0, sizeof(a)/sizeof(int)-1, k)<<endl;
    
}

线性时间选择

#include<iostream>
#include<vector>
#include <algorithm>
#include <random>
using namespace std;
int n, k;
vector<int>vec;
int partition(vector<int>& a, int s, int e, int hub) {
	int i = s, j = e;
	while (i <= e && j >= s) {
		while (a[i] < hub)i++;
		while (a[j] > hub)j--;
		if (i >= j) { 
			break;
		}
		else {
			swap(a[i], a[j]);
		}
	}
	return j;
}
void Sort(vector<int>& a, int s, int e)
{
	for (int i = s; i < e; i++) {
		int min = i;
		for (int j = i + 1; j < e; j++)
			if (a[j] < a[min])
				min = j;
		swap(vec[i], vec[min]);
	}
}
int Mid_kth_Smaller(vector<int>& a, int s, int e, int k) {
	if (e - s < 5) {
		Sort(a, s, e);
		return a[s + k - 1];
	}
	int standard;
	for (int i = 0; i <= (e - s - 4) / 5; i++) {
		standard = s + i * 5;
		if (a[standard] > a[standard + 1])
			swap(a[standard], a[standard + 1]);

		if (a[standard + 2] > a[standard + 3])
			swap(a[standard + 2], a[standard + 3]);

		if (a[standard] > a[standard + 2])
		{
			swap(a[standard], a[standard + 2]);
			swap(a[standard + 1], a[standard + 3]);
		}

		if (a[standard + 1] > a[standard + 4])
		{
			swap(a[standard + 1], a[standard + 4]);
		}

		if (a[standard + 1] > a[standard + 2])
		{
			swap(a[standard + 1], a[standard + 2]);
			swap(a[standard + 3], a[standard + 4]);
		}

		if (a[standard + 2] > a[standard + 4])
		{
			swap(a[standard + 2], a[standard + 4]);
		}

		swap(a[standard + 2], a[s + i]);
	}
	int mid = Mid_kth_Smaller(a, s, s + (e - s - 4) / 5, ((e - s - 4) / 5 + 1) / 2 + 1);
	int mid_location = partition(a, s, e - 1, mid);
	int mid_rank = mid_location - s + 1;
	if (k == mid_rank) {
		return a[mid_location];
	}
	else if (k < mid_rank) {
		return Mid_kth_Smaller(a, s, mid_location, k);
	}
	else {
		return Mid_kth_Smaller(a, mid_location + 1, e, k - mid_rank);
	}
}
int main()
{
	int temp;
	cin >> n >> k;
	uniform_real_distribution<float> u(0, 100);
	default_random_engine e(time(NULL));
	for (int i = 0; i < n; i++)
	{
		temp = (int)u(e);
		vec.push_back(temp);
	}
	for (int i = 0; i < n; i++) {
		cout << vec[i] << " ";
	}
	cout << endl;
	cout << Mid_kth_Smaller(vec, 0, n, k) << endl;
}

期末考试出了个写线性时间选择的递归公式,我没写出来( Ĭ ^ Ĭ )。

实验八 最大子段和

#include<iostream>
#include<random>
#include<ctime>
#include<stdlib.h>
#include <random>
using namespace std;
struct maxSubSum{
    int* arr;
 maxSubSum(){}
 ~maxSubSum(){
    free(arr);
}

 void Create_Psg(int n){
     uniform_real_distribution<float> u(-90, 100);
     default_random_engine e(time(0));
    arr = (int*)malloc(sizeof(int) * (n + 2));
    cout << "原段为:";
    for (int i = 1; i < n; i++){
        arr[i] = (int)u(e);
        cout << arr[i] <<",";
    }
    arr[n] = (int)u(e);
    cout << arr[n];
    cout << endl;
}
void Enumeration(int n){//暴力枚举
    int l = 0, r = 0, s = -999999;
    for (int i = 1; i <= n; i++)
        for (int j = i ; j <= n; j++) {
            int sum = 0;
            for (int k = i; k <= j; k++) {
                sum += arr[k];

            }
            if (sum > s){
                s = sum;
                l = i;
                r = j;
            }
        }
    cout << "暴力穷举" <<":";
    cout  << l << "~"  << r;
    cout << endl << "值为" << s << endl;
}
void Dp(int r)//动态规划
{
    int* fa = new int[r + 1];
    int* dp = new int[r + 1];
    int s = arr[1], rf = 1;
    fa[1] = 1;
    dp[1] = arr[1];
    for (int i = 2; i <= r; i++){
        if (dp[i - 1] > 0){
            dp[i] = arr[i] + dp[i - 1];
            fa[i] = fa[i - 1];
        }
        else {
            dp[i] = arr[i];
            fa[i] = i;
        }

        if (dp[i] > s){
            s = dp[i];
            rf = i;
        }
    }
    cout << "动态规划" <<":";
    cout << fa[rf] << "~" << rf;
    cout << endl << "值为" << s << endl;
}
int Divide_and_Conquer(int l, int r, int& fa, int& fb, int f){//分治{
    int sum = 0;
    if (l == r){
        if (arr[l] > 0){
            sum = arr[l];
            fa = l;
            fb = l;
        }
        else  {
            sum = 0;
            fa = 0;
            fb = 0;
        }
    }
    else
    {
        int mid = (l + r) / 2;
        int la = 0, lb = 0, ra = 0, rb = 0, ma = mid + 1, mb = mid;
        int lsum = Divide_and_Conquer(l, mid, la, lb, 1);
        int rsum = Divide_and_Conquer(mid + 1, r, ra, rb, 1);

        int s1 = 0, ls = 0;
        for (int i = mid; i >= l; i--) {
            ls += arr[i];
            if (ls > s1) {
                s1 = ls;
                ma = i;
            }
        }
        int s2 = 0, rs = 0;
        for (int i = mid + 1; i <= r; i++) {
            rs += arr[i];
            if (rs > s2){
                s2 = rs;
                mb = i;
            }
        }
        sum = s1 + s2;
        fa = ma;
        fb = mb;
        if (sum < lsum) {
            sum = lsum;
            fa = la;
            fb = lb;
        }
        if (sum < rsum){
            sum = rsum;
            fa = ra;
            fb = rb;
        }
    }
    if (!f){
        cout << "分治法"<<":";
        cout << fa << "~"  << fb;
        cout << endl << "值为" << sum << endl;
    }

    return sum;
}
};
int main()
{
    int n;
    cin >> n;
    maxSubSum subsegment;
    subsegment.Create_Psg(n);
    int a, b;
    subsegment.Divide_and_Conquer(1, n, a, b, 0);

    subsegment.Enumeration(n); 
   subsegment.Dp(n);
}

  懒得拆了,三种方法合在一起了。为了降重把变量名改的挺抽象的,输入为待处理段的长度。

以上就是实验的所有内容了,本人仅负责转载,内容不一定原创!

  • 0
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值