조합 최적화로 페인트 영역 풀기
Advent Calendar 14 일 기사 조합 최적화로 벽 로직 풀기
이게 뭐야
페인트 영역을 파이썬에서 조합 최적화 모델을 만들어 풀어 라.
푸는 재미는 모델링을 고안하는 것입니다.
자신도 시도하고 싶은 사람은 아래를 참조하십시오.
문제
아래는 왼쪽이 문제이고 오른쪽이 대답입니다.
data
에 타일의 그룹이, nums
에 힌트의 「행, 열, 개수」가 들어 있다고 합니다.파이썬
import pandas as pd, matplotlib.pyplot as plt
from pulp import LpProblem, lpSum, value
from ortoolpy import addbinvars, unionfind
data = """\
AABBC
DEFBC
DGFHH
DGIJH
KKLJH""".splitlines()
nums = [[0,1,3], [3,2,2], [4,1,1]]
변수 테이블
아래와 같은 변수 테이블을 작성합니다. 각 행의 변수는 0 또는 1을 취합니다.
변수의 값이 1이면 해당 행 해당 열의 질량이 검정색입니다.
"자"는
data
의 값입니다.행
열
글자
Var
0
0
0
A
v000001
1
0
1
A
v000002
...
...
...
...
...
파이썬
ni, nj = len(data), len(data[0])
a = pd.DataFrame([(i,j,data[i][j]) for i in range(ni)
for j in range(nj)], columns=list('行列字'))
a['Var'] = addbinvars(len(a))
a[:2]
수리 모델을 만들어 풀다
변수 테이블을 만들었으므로 페인트 영역의 해가되도록 제약 조건을 추가하고 수리 모델을 만들고 해결합시다.
query
에서 2x2를 꺼내 검정색 수를 1,2,3으로 설정합니다. 파이썬
m = LpProblem()
for i in range(ni-1):
for j in range(nj-1):
e = lpSum(a.query(f'{i}<=行<={i+1}&{j}<=列<={j+1}').Var)
m += e >= 1 # 2×2の白がない
m += e <= 3 # 2×2の黒がない
for _,v in a.groupby('字'):
for vi, vj in zip(v.Var, v.Var[1:]):
m += vi == vj # タイル内は同じ
for i, j, k in nums: # 数字は周りの黒の数と等しい
m += lpSum(a.query(f'abs(行-{i})+abs(列-{j})==1').Var) == k
while True:
m.solve()
r = a.Var.apply(value)
if unionfind.isconnected(r.values.reshape(ni,nj)):
break # 全ての黒がつながる
m += lpSum(a[r==0].Var) >= 1
결과 표시
파이썬
plt.imshow((1-r).values.reshape(ni,nj), cmap='gray', interpolation='none')
plt.show()
풀리고 있는지 확인할 수 있습니다.
이상
Reference
이 문제에 관하여(조합 최적화로 페인트 영역 풀기), 우리는 이곳에서 더 많은 자료를 발견하고 링크를 클릭하여 보았다 https://qiita.com/SaitoTsutomu/items/5815c64ec23b8c88eee0텍스트를 자유롭게 공유하거나 복사할 수 있습니다.하지만 이 문서의 URL은 참조 URL로 남겨 두십시오.
우수한 개발자 콘텐츠 발견에 전념 (Collection and Share based on the CC Protocol.)