继续来水一道题。。。
一、 实验目的
- 加深对求解一个3 * 3方格两两相邻为质数求解算法的理解;
- 通过本次试验掌握将算法转换为上机操作;
- 加深对深度优先搜索思想的理解,理解回溯原理即实现过程,并利用其解决生活中的问题。
二、实验内容
任务:求解填字游戏问题
在3*3个方格的方阵中填入数字1-10的某9个数字,每个方格填-一个整
数,使所有相邻两个方格内的两个整数之和为素数。编写一个程序,求出所有
满足这个要求的数字的填法。
三、实验原理
首先本题就是求一个3 * 3方格中填十个数1-10,使得两两相邻的之和为质数,求解所有方案!
本题适合采用深度优先搜索DFS来求解:
- 从(0,0)开始向右搜索,搜到(3,0)结束
- 搜索时记录那些点被用过,下一个点一定是没有被用过的点,使用vis数组标记
- 退出条件:搜索到 x == 3时,即此时九个点都已经填了一遍值,输出填入的九个值
- 改点是否可以填入,是否合法:使用check函数来检查一下,由于是从左向右开始填起,所以相邻元素只需要考虑上和下两个方向,check函数加上判断边界的条件即可。
- 若该点合法,则填入该点,否则继续循环找一个可选点。
- 判断边界:即不能超出 3 * 3 的范围,到了最右边要进行换行,否则横坐标直接++即可!具体实现:
if(y == 2) dfs(x + 1, 0); else dfs(x, y + 1);
- 最后取消标记,回溯上一个点,找下一种选择情况。
四、程序代码
说明: 深度优先搜索一遍即可。
函数说明:
- Isprime():用来判断是否是质数
- Check():用来判断当前位置放入一个值是否合法,即相邻是否为质数。
- Dfs():用来深度优先搜索一遍九个位置,并将符合条件的进行打印
代码如下:
#include <iostream>
using namespace std;
int a[3][3], count;
bool vis[10];
bool isprime(int n)
{
for(int i = 2; i * i <= n; i++){
if(n % i == 0) return false;
}
return true;
}
bool check(int x, int y, int k)
{
// 上
if(x - 1 >= 0 && !isprime(a[x - 1][y] + k)) return false;
// 左
if(y - 1 >= 0 && !isprime(a[x][y - 1] + k)) return false;
return true;
}
void dfs(int x, int y)
{
if(x == 3){
for(int i = 0; i < 3; i++){
for(int j = 0; j < 3; j++){
cout << a[i][j] << " ";
}
cout << endl;
}
cout << endl;
count ++;
return;
}
for(int i = 1; i <= 10; i++){
if(!vis[i] && check(x, y, i)){
a[x][y] = i; vis[i] = true;
if(y == 2) dfs(x + 1, 0);
else dfs(x, y + 1);
a[x][y] = 0; vis[i] = false;
}
}
}
int main()
{
dfs(0, 0);
cout << "Total: " << count << endl;
return 0;
}
五、实验结果
说明:总共有128种方案,截图太多,保留第一张和最后一张!
测试一:
测试二:
六、分析总结
- 通过本次实验掌握了求解3 * 3 保证相邻为质数填空的问题,了解了一些相关算法的实现及求解原理。
- 了解并掌握了深度优先搜索算法和回溯算法的实现原理及求解过程,加深了对该算法原理的理解和实现。
- 明白了回溯的过程及递归解决问题的一些优点,要将所学所掌握的优秀解决问题算法用到现实世界中来解决一些不好用人力解决的问题。