IT数码 购物 网址 头条 软件 日历 阅读 图书馆
TxT小说阅读器
↓语音阅读,小说下载,古典文学↓
图片批量下载器
↓批量下载图片,美女图库↓
图片自动播放器
↓图片自动播放器↓
一键清除垃圾
↓轻轻一点,清除系统垃圾↓
开发: C++知识库 Java知识库 JavaScript Python PHP知识库 人工智能 区块链 大数据 移动开发 嵌入式 开发工具 数据结构与算法 开发测试 游戏开发 网络协议 系统运维
教程: HTML教程 CSS教程 JavaScript教程 Go语言教程 JQuery教程 VUE教程 VUE3教程 Bootstrap教程 SQL数据库教程 C语言教程 C++教程 Java教程 Python教程 Python3教程 C#教程
数码: 电脑 笔记本 显卡 显示器 固态硬盘 硬盘 耳机 手机 iphone vivo oppo 小米 华为 单反 装机 图拉丁
 
   -> 数据结构与算法 -> 程序员的算法趣题Q69: 蓝白歌会(1) -> 正文阅读

[数据结构与算法]程序员的算法趣题Q69: 蓝白歌会(1)

作者:4.%20%E5%90%8E%E8%AE%B0

目录

1. 问题描述

2. 解题分析

2.1 基本思路

2.2 算法流程

?2.3 实现要点

3. 代码及测试

4. 后记


1. 问题描述

问题:当有4*6=24个人,以12人为一组分为两组时,求所需移动次数最多的起始状态有多少种?

2. 解题分析

2.1 基本思路

????????由于终止状态是确定的(4个),所以适合于逆向搜索(本系列前面出现过不少逆向思维解决的问题例)。

????????位置交换动作是可逆的,从4个确定性的终止状态开始,通过合理的位置交换操作(确保距离最小化)寻找距离4个确定性的终止状态最远的初始状态。这个显然是图搜索中最大距离问题,适合于用广度优先搜索算法。

????????另外,由于本题要求不仅找出最大距离,还要求找出满足这一条件的初始状态的个数,所以相当于要找出再广度优先搜索中出现在最远一层的所有状态的个数。

2.2 算法流程

????????基于广度优先搜索的算法流程如下所示:

?2.3 实现要点

????????当前人员状态用二维数组(本题解用numpy数组)表示,为了方便判断,与棋盘问题类似采用了外加围栏的方式。

????????如以上算法流程图中所述,由于最后需要最终层的所有状态个数,因此visited以字典的方式记录状态以及其对应的距离。

????????由于numpy数组不能用作dict的key,所以,表示状态的numpy二维数组先变换为一维数组,然后转变为tuple,用作visited的key,而距离(层数, curStep)。存入队列时,则是将前述visited的key与距离(层数, curStep)组成一个嵌套式的tuple再存入。注意队列q与visited的这两种存储方式的区别。

????????在每个格子上查询是否可以交换时,只考虑它与右边一格以及下边一格交换的可能性。这样按行扫描下去,不会遗漏也不会产生不必要的重复。这个技巧也是在前面的题目中已经出现过。

3. 代码及测试

# -*- coding: utf-8 -*-
"""
Created on Mon Oct 18 07:39:04 2021

@author: chenxy
"""

import sys
import time
import datetime
import math
# import random
from   typing import List
from   collections import deque
import itertools as it
import numpy as np

N = 4
M = 6

seat = np.ones((N,M))
initState1 = seat.copy()
initState1[:,:M//2] = -1
initState2 = seat.copy()
initState2[:,M//2:] = -1
initState3 = seat.copy()
initState3[:N//2,:] = -1
initState4 = seat.copy()
initState4[N//2:,:] = -1

q = deque()
visited = dict()

q.append((tuple(np.reshape(initState1, (N*M,))),0))
q.append((tuple(np.reshape(initState2, (N*M,))),0))
q.append((tuple(np.reshape(initState3, (N*M,))),0))
q.append((tuple(np.reshape(initState4, (N*M,))),0))

visited[tuple(np.reshape(initState1, (N*M,)))] = 0
visited[tuple(np.reshape(initState2, (N*M,)))] = 0
visited[tuple(np.reshape(initState3, (N*M,)))] = 0
visited[tuple(np.reshape(initState4, (N*M,)))] = 0

ansLst = []
tStart = time.perf_counter()
while len(q) > 0:    
    curState, curStep = q.popleft()
    # print(curState,curStep)
    curExt = np.zeros((N+2,M+2))
    curExt[1:N+1,1:M+1] = np.reshape(curState, (N,M))
    for k in range(1,N+1):
        for l in range(1,M+1):
            if curExt[k,l] * curExt[k,l+1] == -1:
                curExt[k,l] *= -1
                curExt[k,l+1] *= -1
                nxtState = curExt[1:N+1,1:M+1]
                if tuple(np.reshape(nxtState, (N*M,))) not in visited:
                    q.append((tuple(np.reshape(nxtState, (N*M,))),curStep+1))
                    visited[tuple(np.reshape(nxtState, (N*M,)))] = curStep+1                    
                curExt[k,l] *= -1
                curExt[k,l+1] *= -1            
            if curExt[k,l] * curExt[k+1,l] == -1:
                curExt[k,l] *= -1
                curExt[k+1,l] *= -1
                nxtState = curExt[1:N+1,1:M+1]
                if tuple(np.reshape(nxtState, (N*M,))) not in visited:
                    q.append((tuple(np.reshape(nxtState, (N*M,))),curStep+1))
                    visited[tuple(np.reshape(nxtState, (N*M,)))] = curStep+1                    
                curExt[k,l] *= -1
                curExt[k+1,l] *= -1


ansSteps = curStep    
numStates = 0
for key in visited:
    if visited[key] == ansSteps:
        ansLst.append(key)
        numStates += 1
tCost  = time.perf_counter() - tStart

print('N={0}, M={1}, ansSteps={2}, numStates={3}, {4:6.3f}(sec)'.format(N,M,ansSteps,numStates,tCost))        

运行结果:

????????N=4, M=4, ansSteps=10, numStates=64, ?1.380(sec)

????????N=4, M=6, ansSteps=20, numStates=4, 479.002(sec)

4. 后记

? ? ? ? 这本书的压卷之题。但是看着顺眼一点(思路对上了^-^)所以就先拉出来办了。但是,以上题解虽然给出了正确解答,速度却实在不能恭维!需要严重优化。不过也是,压轴之题如果就这么简单地解决了也着实不像话(太不把村长当干部了)。欲知后事如何,且听下回分解。我会回来的。。。

?????本系列总目录参见:程序员的算法趣题:详细分析和Python全解

  数据结构与算法 最新文章
【力扣106】 从中序与后续遍历序列构造二叉
leetcode 322 零钱兑换
哈希的应用:海量数据处理
动态规划|最短Hamilton路径
华为机试_HJ41 称砝码【中等】【menset】【
【C与数据结构】——寒假提高每日练习Day1
基础算法——堆排序
2023王道数据结构线性表--单链表课后习题部
LeetCode 之 反转链表的一部分
【题解】lintcode必刷50题<有效的括号序列
上一篇文章      下一篇文章      查看所有文章
加:2021-10-19 12:08:35  更:2021-10-19 12:09:46 
 
开发: C++知识库 Java知识库 JavaScript Python PHP知识库 人工智能 区块链 大数据 移动开发 嵌入式 开发工具 数据结构与算法 开发测试 游戏开发 网络协议 系统运维
教程: HTML教程 CSS教程 JavaScript教程 Go语言教程 JQuery教程 VUE教程 VUE3教程 Bootstrap教程 SQL数据库教程 C语言教程 C++教程 Java教程 Python教程 Python3教程 C#教程
数码: 电脑 笔记本 显卡 显示器 固态硬盘 硬盘 耳机 手机 iphone vivo oppo 小米 华为 单反 装机 图拉丁

360图书馆 购物 三丰科技 阅读网 日历 万年历 2024年11日历 -2024/11/26 7:20:32-

图片自动播放器
↓图片自动播放器↓
TxT小说阅读器
↓语音阅读,小说下载,古典文学↓
一键清除垃圾
↓轻轻一点,清除系统垃圾↓
图片批量下载器
↓批量下载图片,美女图库↓
  网站联系: qq:121756557 email:121756557@qq.com  IT数码