from itertools import product
# Slot index mapping supplied: weekdays only, AM/PM in order.
slots = [("周一","AM"),("周一","PM"),("周二","AM"),("周二","PM"),("周三","AM"),("周三","PM"),("周四","AM"),("周四","PM"),("周五","AM"),("周五","PM"),("下周一","AM"),("下周一","PM")]
people = {"S":{"Eva","Finn"},"API":{"Eva"},"UI":{"Finn"},"X":{"Eva"},"I":{"Eva","Finn"},"Q":{"Gia"},"F":{"Eva"},"A":{"Eva","Gia"}}
blocked={"Eva":{3},"Finn":{6},"Gia":set(range(8))}
# Explicit lower-bound enumeration: fixed sequential prerequisite work and windows.
# S earliest at 0; API's 3 ordered work slots avoid Eva slot 3; X (full only) follows API.
# I earliest is max(prerequisite finish, approval+1); Q requires two post-I Gia slots;
# F follows Q; A follows F and must occupy customer slot 10 or 11.
def candidates(full, delayed):
    gate_end=7 if delayed else 6
    out=[]
    for s in range(12):
      if s!=0: continue
      api_choices=[c for c in product(range(1,12), repeat=3) if list(c)==sorted(set(c)) and all(x not in blocked['Eva'] for x in c)]
      for api in api_choices:
       api_end=api[-1]+1
       x_choices=[()] if not full else [c for c in product(range(api_end,12),repeat=2) if list(c)==sorted(set(c)) and all(x not in blocked['Eva'] for x in c)]
       for x in x_choices:
        xend=(x[-1]+1 if x else api_end)
        # UI two ordered slots, after S, Finn available
        for ui in product(range(1,12),repeat=2):
         if list(ui)!=sorted(set(ui)) or any(i in blocked['Finn'] for i in ui): continue
         prereq=max(api_end,xend,ui[-1]+1,gate_end+1)
         i=prereq
         if i>=12 or i in blocked['Finn']: continue
         # Q may split: two successive available work slots, strictly after I
         for q in product(range(i+1,12),repeat=2):
          if list(q)!=sorted(set(q)) or any(k in blocked['Gia'] for k in q): continue
          f=max(q[-1]+1,0)
          if f>=12 or f in blocked['Eva']: continue
          for a in (10,11):
           if a>=f+1 and a not in blocked['Eva'] and a not in blocked['Gia']:
            out.append((api,ui,x,i,q,f,a))
    return min(out,key=lambda z:z[-1]) if out else None
for full in (False,True):
 for delayed in (False,True):
  r=candidates(full,delayed)
  label=('完整版' if full else '缩减版')+('审批推迟' if delayed else '审批如期')
  if r is None: print(label+': 无可行解；下界 I≥'+str(8 if delayed else 7)+', Q最早占'+str((9,10) if delayed else (8,9))+', F最早'+str(11 if delayed else 10)+', A最早'+str(12 if delayed else 11))
  else:
   api,ui,x,i,q,f,a=r
   assert i>max(api[-1],ui[-1],(x[-1] if x else -1),6 if not delayed else 7)
   assert q[0]>i and f>q[-1] and a>f
   assert all(k not in blocked[p] for p,ks in [('Eva',api),('Finn',ui)] for k in ks)
   print(f'{label}: S0; API{api}; UI{ui}; X{x or "不做"}; I{i}; Q{q}; F{f}; A{a}; 验收slot{a} {slots[a]}')
print(' effort slots—full: Eva9 (S1+API3+X2+I1+F1+A1), Finn4 (S1+UI2+I1), Gia3 (Q2+A1); reduced: Eva7, Finn4, Gia3.')
