88、元素柱击打问题建模

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


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)

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值