一、实验目的
二、使用仪器、材料 PC微机; Windows 操作系统,VS2015编译环境(不限);
|
四、实验过程原始记录(数据、图表、计算等) 1. 求解钱币兑换问题 本题采用蛮力法的思想,搜索所有的解空间并找到可行解。在本题中,兑换1分硬币的个数为x,兑换2分硬币的个数为y,兑换5分硬币的个数为z,并由1*x+2*y+5*z是否等于10来判断是否是可行解。 具体求解代码如下: #define n 10 int a = 1; int b = 2; int c = 5; void solve() { int num = 0; int x, y, z; for (x = 0; x <= n / a; x++) { for (y = 0; y <= n / b; y++) { for (z = 0; z <= n / c; z++) { if (a * x + b * y + c * z == n) { num++; cout << "兑法" << num << ": "; cout << x << "个1分硬币 " << y << "个2分硬币 " << z <<"个5分硬币" << endl;
} } } } cout << "总兑换个数 " << num << endl; } 输入案例:n为10 时间复杂度分析: 本题采用蛮力法的思想,利用穷举所有可行解,故时间复杂度为O(n^3),本题规模较小,算法运行效率在可接受的范围内。 求解填字游戏问题 回溯法:从根节点出发,以深度优先搜索方式搜索整个解空间。回溯法以这种工作方式递归地在解空间中搜索,直到找到所要求的解或解空间所有解都被遍历过为止。 本题利用回溯法,对于已选择的元素进行标记,以便后续不重复选择。若遍历完所有数字都找不到合适的数字填进去,就回溯到上一结点继续寻找可行解。 具体求解代码如下: int a[n]; bool v[N + 1] = { false }; //判断素数 bool isPrim(int a) { if (a == 1) return false; for (int i = 2; i < a / 2; i++) { if (a % i == 0) { return false; } } return true; } void solve(int m, int& num) { if (m > n) { num = num + 1; for (int i = 1; i < 10; i++) { cout << a[i] << " "; } cout << endl; } else { for (int i = 1; i <= N; i++) { if (v[i] == false) {//找十个数字中没被选过的 a[m] = i; if (m > 3 && !isPrim(a[m - 3] + a[m]) || m % 3 != 1 && !isPrim(a[m - 1] + a[m])) {//相邻节点和得是素数 continue; } v[i] = true;//标记这个数字已经被选过了 solve(m + 1, num); v[i] = false;//回溯还原 } } } } 输入案例: 案例1:N=10 案例2:N=12 时间复杂度分析:本题采用回溯法的思想求解问题,共递归n层,平均情况下,时间复杂度为 O(N**n),N为可选择的数字的个数。 |