IDA*(迭代加深+预估函数A*)
ACwing.181.回转游戏
https://www.acwing.com/problem/content/183/
# 下标打表
# 依次为ABCDEFGH操作
pos = [
[0, 2, 6, 11, 15, 20, 22],
[1, 3, 8, 12, 17, 21, 23],
[10, 9, 8, 7, 6, 5, 4],
[19, 18, 17, 16, 15, 14, 13],
[23, 21, 17, 12, 8, 3, 1],
[22, 20, 15, 11, 6, 2, 0],
[13, 14, 15, 16, 17, 18, 19],
[4, 5, 6, 7, 8, 9, 10]
]
# 中心8个空的下标
center = [6, 7, 8, 12, 17, 16, 15, 11]
# 如果该操作已经操作过了,反向的就不操作了,标记反向的下标
reverse = [5, 4, 7, 6, 1, 0, 3, 2]
# 计算中心数量最大的点的值,8减一下表示至少加深多少步才能结束
def f():
cnt = [0] * 4
for i in center:
cnt[lis[i]] += 1
max_num = max(cnt)
return 8 - max_num
def dfs(depth, max_depth, pre):
global lis
# 如果当前+预估大于当前最大深度则退出
if depth + f() > max_depth:
return False
# 等于0表示当前已经都为一个数了,找到结果
if f() == 0:
return True
# 拷贝,用于回溯
temp = lis[:]
for i in range(8):
# 如果上一步已经操作过了,就不反向操作了,因为无意义
if reverse[i] == pre:
continue
# 对应的拉取操作
num = lis[pos[i][0]]
for j in range(6):
lis[pos[i][j]] = lis[pos[i][j + 1]]
lis[pos[i][6]] = num
# 保存路径
path.append(chr(65 + i))
if dfs(depth + 1, max_depth, i):
return True
# 回溯
lis = temp[:]
path.pop()
return False
while True:
path = []
s = list(input().split())
if s[0] == '0':
break
lis = list(map(int, s))
# 不断加深迭代,不知道最大深度,就写了个100
max_depth = 0
while max_depth<100:
if dfs(0, max_depth, -1):
break
max_depth+=1
if not max_depth:
print('No moves needed')
else:
print(''.join(path))
print(lis[6])
ACwing.180.排书
https://www.acwing.com/problem/content/182/
# 计算多少个尾部序列(lis[i]+1!=lis[i+1])
# 例如:只有一个数需要交换时(1,2,4,5,3,6)要修改12,45,3三个序列的后缀点,则最少需要操作 需要修改的后缀序列点/3 向上取整
def f():
cnt = 0
for i in range(1,n):
if nums[i]-nums[i-1]!=1:
cnt +=1
return int((cnt+2)/3)
def check():
for i in range(1,n):
if nums[i]-nums[i-1]!=1:
return False
return True
def dfs(idx,max_depth):
global nums
if f()+idx>max_depth:
return False
# 当前全有序则返回,改成f()==0也成立
if check():
return True
# 状态转移
for len in range(1,n+1):
# 枚举区间左右边界
for l in range(0,n-len+1):
r = l+len-1
# 拷贝
lis = nums[:]
for k in range(r+1,n):
nums = lis[:l]+lis[r+1:k+1]+lis[l:r+1]+lis[k+1:]
![请添加图片描述](https://img-blog.csdnimg.cn/direct/91a952744507429f97a19dad08bf56c8.png)
if dfs(idx+1,max_depth):
return True
nums = lis[:]
return False
T = int(input())
for _ in range(T):
n = int(input())
nums = list(map(int,input().split()))
max_depth = 0
while max_depth<5 and not dfs(0,max_depth):
max_depth+=1
if max_depth>=5:
print('5 or more')
else:
print(max_depth)