在N*N的棋盘上(1<=N<=10)请填入1,2,...N2共N2个数,使得任意两个相邻的数之和为素数。

该博客探讨了一个N*N棋盘填数问题,要求填入1到N²的整数,使得任意相邻两个数之和为素数。通过C语言实现算法,包括判断素数、选择合适整数、检查合理性、回溯和输出结果等步骤。

#include <stdio.h>

#define N 10

 

int A[N+1][N+1];                /*格子*/

int B[N*N+1]={0,1,0};           /*为已经填入的数标记*/

int pos=1;                      /*指向当前格子*/

struct

{

    int x;

    int y;

    int num;

}D[N*N+1];

 

int isPrime(int m)       /*判断是否是素数*/

{

    int i;

    if(m==2)

        return 1;

    if(m==1 || m%2==0)

        return 0;

    for(i=3;i*i<=m;)

    {

        if(m%i==0)

            return 0;

        i+=2;

    }

1.问题描述 八码难题是在一个3×3的棋盘上随机分布着八位(1-8),与空白格相连的上下左右的码可以移动到空白格中, 通过移动码,使得棋盘转化为目标状态,如下图所示: 2.问题分析 因为只有紧靠空白格的码才能移动,因此仅为空白格制定上、下、左、右4种走步,空白格移动的唯一约束是不能移出棋盘。 为了便于编程实现,用码0来代替空白格,这样问题就转换成了通过交换码0它上下左右的码位置,最终达到目标状态 的问题。 3.算法设计 程序实现过程中用到的据结构有: (1)八码的状态类State 每个节点的状态包括节点状态state、节点的父节点parent节点中空格的可移动方向direction。其中初始节点没有父节点。 (2)openTable用来存放待扩展的节点。 算法执的步骤: (1)设置初始状态initial_state对象,并从该对象开始进宽度优先搜索; (2)把初始节点放入openTable中。 (3)如果open表非空,做循环 ①从open表中最前端取出第一个节点node ②如果node.statetarget_state相等,则查找并记录最优求解路径,并返回最优路径path、扩展节点n生成节点generate_Numbers; ③否则调用generateSubStates方法获取当前节点node的所有子节点,并将其放入openTable的末尾。返回①继续执。 4.填空完善程序。 import numpy as np import copy class State: symbol = 0 def __init__(self, state, directionFlag=None, parent=None): self.state = state #3*3的组存放八码的状态 self.direction = ['up', 'down', 'right', 'left'] #移动的方向 if directionFlag: self.direction.remove(directionFlag) #删除节点返回父节点的移动方向 self.parent = parent #记录节点的父节点 def showInfo(self,flag): #打印输出八码的状态 for i in range(3): for j in range(3): print(self.state[i, j], end=' ') print() if flag:print(' ↓') return def getEmptyPos(self): #查找0即空格的位置 postion = np.where(self.state == self.1) return postion def generateSubStates(self):#生成子节点 if not self.direction: #如果空格没有可以移动的方向 return [] subStates = [] #存放当前节点所有子节点的表 row, col = self.getEmptyPos() #记录0即空格的位置 if 'left' in self.direction and col > 0: #当前状态允许向左移动,且其号大于0 s = copy.deepcopy(self.state) #深拷贝 #标志位symbol=0向左移动,产生新的状态节点,加入到subStates中 s[row, col],s[row, col-1]=s[row, col-1],s[row, col] #交换0其左侧字的位置 new_State = State(s, directionFlag='right', parent=self) #创建一个新节点,且其不可以向右移动,并记录其父节点 subStates.append(new_State) if 'right' in self.direction and col<2: #当前状态允许向右移动,且其号小于2 s = copy.deepcopy(self.state) # 标志位symbol=0向右移动,产生新的状态节点,加入到subStates中 s[row, col],s[row, col+1]=s[row, col+1],s[row, col] new_State = State(s, directionFlag='left', parent=self) subStates.append(2) if 'up' in self.direction and row > 0: #当前状态允许向上移动,且其号大于0 s = copy.deepcopy(self.state) # 标志位symbol=0向上移动,产生新的状态节点,加入到subStates中 s[row, col],s[row-1, col]=s[row-1, col],s[row, col] new_State = State(s, directionFlag='down', parent=self) subStates.append(new_State) if 'down' in self.direction and 【3】: #当前状态允许向下移动,且其号小于2 s = copy.deepcopy(self.state) # 标志位symbol=0向下移动,产生新的状态节点,加入到subStates中 s[row, col],s[row+1, col]=s[row+1, col],s[row, col] new_State = State(s, directionFlag='up', parent=self) subStates.append(new_State) return 【4】 #返回所有生成的子节点 def BFS(self): openTable = [] #利用open表存放待扩展的节点 openTable.append(self)#将初始状态放入Open表 n = 0 #记录已扩展节点的个数 generate_Numbers=1 while len(【5】) > 0: #open表不为空 node = openTable.pop(0) #获取open表中的第一个节点 if np.array_equal(node.state,target_state): #节点是目标节点 path=[] #记录解路径,从目标节点往回找 while node.parent: #当前节点存在父节点 path.append(node.parent) #将父节点存入path表中 node = node.parent path.reverse() #路径反向,即转为从初始节点到目标节点的解路径 return 【6】, n, generate_Numbers #返回解路径、扩展的节点个数n生成的节点个数generate_Numbers else: #当前节点不是目标节点 subStates = node.generateSubStates() #获取当前节点的子节点 generate_Numbers+=len(subStates) if len(subStates)>0: #当前节点存在子节点 openTable.extend(subStates) #将子节点存入open表的末尾 n += 1 #已扩展节点的个数1 else: return None, None, None #无解 target_state = np.array([[7, 5, 8], [2, 4, 1], [3, 6, 0]]) initial_state = State(np.array([[0, 7, 8], [2, 5, 4], [3, 6, 1]])) path,n1,n2 = initial_state.BFS() if path: #找到解路径 for node in path: #打印解路径 node.【7】(1) #调用方法打印最优路径上的状态 target=State(target_state) #单独打印目标节点 target.showInfo(0) print("扩展节点:%d" % n1) print("生成节点:%d" % n2)1空 第2空 第3空 第4空 第5空 第6空 第7空
最新发布
10-27
评论 3
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
红包 添加红包
表情包 插入表情
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值