IDA*算法,A*+迭代加深,Python

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)
  • 2
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值