88、元素柱击打问题建模

有n个柱子,每个柱子有k个面,敲击后其本身及前后的柱子会顺时针旋转一定的角度度,问对任意一种初始状态下的柱子,应当如何敲击能够保证其都面对着特定的一面

88、元素柱击打问题建模_第1张图片


pro = """
有n个柱子,每个柱子有k个面,敲击后其本身及前后的柱子会顺时针旋转一定的角度度,问对任意一种初始状态下的柱子,应当如何敲击能够保证其都面对着特定的一面
"""

import re
from pyscipopt import Model, quicksum

def case():
    A, k, isEnd2End = [0, 0, 0, 1], 4, False
    # A, k, isEnd2End = [0, 1, 2, 3], 4, False
    # A, k, isEnd2End = [0, 0, 2, 3], 4, False

    A, k, isEnd2End = [1, 1, 0, 0, 0], 2, False
    A, k, isEnd2End = [1, 1, 0, 0, 1], 2, True

    return A, k, isEnd2End

def IP(A, k, isEnd2End, timeLimit=100, isPrint=True):
    # 建模求解
    model = Model("IP")
    n = len(A)
    X = [model.addVar(vtype="I", name="X[%s]"%(i)) for i in range(n)]
    B = [model.addVar(vtype="I", name="B[%s]"%(i)) for i in range(n)]

    #击打次数最少
    model.setObjective(quicksum(X[i] for i in range(n)), "minimize")

    #变量内置约束
    for i in range(n):
        model.addCons(X[i] >= 0)

    #每个柱子都面对特定的一面
    if isEnd2End:
        model.addCons(X[n-1] + X[0] + X[1] == k * B[0] - A[0])
        model.addCons(X[n - 1] + X[n - 2] + X[0] == k * B[n - 1] - A[n - 1])
    else:
        model.addCons(X[0] + X[1] == k * B[0] - A[0])
        model.addCons(X[n-1] + X[n-2] == k * B[n-1] - A[n-1])
    for i in range(1, n-1):
        model.addCons(X[i - 1] + X[i] + X[i + 1] == k * B[i] - A[i])

    # 设置求解时间
    model.setRealParam("limits/time", timeLimit)
    model.hideOutput()
    model.optimize()

    if isPrint:
        print("\ngap:", model.getGap())

    X1 = [round(model.getVal(X[i])) for i in range(n)]

    return X1

def resPrint(A, X, k, isEnd2End):
    print("初始序列: {}".format(A))
    print("每个柱子几个面: {}".format(k))
    print("是否首尾相连: {}".format(isEnd2End))
    print("击打序列: {}".format(X))

    n = len(A)
    A1 = [0 for i in range(n)]
    if isEnd2End:
        A1[0] = A[0] + X[n-1] + X[0] + X[1]
        A1[n - 1] = A[n - 1] + X[n - 1] + X[n - 2] + X[0]
    else:
        A1[0] = A[0] + X[0] + X[1]
        A1[n-1] = A[n-1] + X[n-1] + X[n-2]
    for i in range(1, n-1):
        A1[i] = A[i] + X[i-1] + X[i] + X[i+1]
    print("终止序列: {}".format(A1))

if __name__ == '__main__':
    A, k, isEnd2End = case()
    X = IP(A, k, isEnd2End)
    resPrint(A, X, k, isEnd2End)

你可能感兴趣的:(其他,python)