程序员的算法趣题Q67: 不挨着坐是一种礼节吗?

发布时间:2022-07-02 发布网站:脚本宝典
脚本宝典收集整理的这篇文章主要介绍了程序员的算法趣题Q67: 不挨着坐是一种礼节吗?脚本宝典觉得挺不错的,现在分享给大家,也给大家做个参考。

目录

1. 问题描述

2. 解题分析

2.1 基本思路

2.2 动态规划

2.3 算法流程

3. 代码及测试

4. 后记


1. 问题描述

程序员的算法趣题Q67: 不挨着坐是一种礼节吗?

        注意,本问题不区分人,只考虑各个座位被占用的不同顺序的个数。 

 

2. 解题分析

2.1 基本思路

        每个人选座位时,首先看有没有“超空位”(两边都没有挨着人的空位暂称为“超空位”),如果有则优先从“超空位”中选取。如果没有超空位,则从空位中任选一个坐下(空位是一定有的,因为人数和座位数是相等的)。

        由于车厢中的作为安排方式(对面两排),两头两位的座位有一边是一定不挨着人的。如何表达才最方便于实现呢?

        借用棋盘问题中的围栏思想,将两排座位排成一排,但是两头和中间各插入一个dummy座位(不能坐人),这样连同dummy座位总共有15个,可以表达为长度为15的数组。Dummy座位置为”-1”表示不能坐人,正常座位初始化为“0”,被人占据了则复制为“1”。这样,判断一个正常座位是否为“超空位”,只要看它本身是否为0且两边都不是1(即为“0”或者“-1”)。

2.2 动态规划

        考虑已经有k个座位被占了,从当前状态出发往后的剩下的(12-k)个座位被占的顺序数只与当前这个k个座位被占的状态有关,而与它们被占的顺序无关。因此这个可以用动态规划的策略来解决。本题考虑用top-down的方式(递归+memoization)来实现动态规划策略。

2.3 算法流程

        算法流程如下:

程序员的算法趣题Q67: 不挨着坐是一种礼节吗?

 

 

3. 代码及测试

# -*- coding: utf-8 -*-
"""
Created on Sun Oct 17 10:52:39 2021

@author: chenxy
"""

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

memo = dict()

def isFull(pos):
    return np.all(pos[1:7]) and np.all(pos[8:14])

def search(pos):
    
    if tuple(pos) in memo:
        return memo[tuple(pos)]
    if isFull(pos):
        return 1
    
    cnt = 0
    hasSuperEmpty = False
    # Search super empty seat
    for k in [1,2,3,4,5,6,8,9,10,11,12,13]:
        if pos[k]==0 and pos[k-1]!=1 and pos[k+1]!=1:
            pos[k] = 1
            cnt = cnt + search(pos)
            hasSuperEmpty = True
            pos[k] = 0
        
    if not hasSuperEmpty:
        for k in [1,2,3,4,5,6,8,9,10,11,12,13]:
            if pos[k]==0:
                pos[k] = 1
                cnt = cnt + search(pos)
                pos[k] = 0
    memo[tuple(pos)] = cnt
    return cnt

N   = 12 # Can't modify currently
pos = np.zeros(N+3)
pos[N//2+1] = -1
pos[N+2]    = -1

tStart = time.perf_counter()
count = search(pos)
tCost  = time.perf_counter() - tStart
print('count = {0}, tCost = {1:6.3f}(sec)'.format(count,tCost))      

        运行结果:count = 14100480, tCost =  0.032(sec) 

4. 后记

        轻松搞定。

        跳过了前面一些题目先做这道,是因为浏览了一下“高级篇”中的题目,大多数题目想2~3分钟感觉没有头绪,先捏这种一看就觉得“顺眼”的软柿子捏一捏^-^。这种策略对于学习很重要,盲目地死磕一道题目花费太久时间容易产生挫折感从而打击学习的积极性。有些问题一时没有头绪,放在脑袋里供闲暇时间想一想说不定更容易突然就有什么灵感。。。

        上一篇:

        下一篇:

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

脚本宝典总结

以上是脚本宝典为你收集整理的程序员的算法趣题Q67: 不挨着坐是一种礼节吗?全部内容,希望文章能够帮你解决程序员的算法趣题Q67: 不挨着坐是一种礼节吗?所遇到的问题。

如果觉得脚本宝典网站内容还不错,欢迎将脚本宝典推荐好友。

本图文内容来源于网友网络收集整理提供,作为学习参考使用,版权属于原作者。
如您有任何意见或建议可联系处理。小编QQ:384754419,请注明来意。
标签: