google code jam exercise——MilkShakes(2)
继续MilkShakes问题。
之前是使用穷举搜索的方法,能保证结果的准确,但是效率较低,对于large case无法完成测试。后来想用贪心算法来实现。贪心策略是,统计flavor处于malted或unmalted出现的次数,取unmalted出现次数最多的flavor,这样被迫出现的malted的flavor次数会少;取malted出现次数最多的flavor,使得被迫出现malted的次数减少。
在使用贪心算法之前,可以对只有一种选择的customer进行满足,确定一部分flavor。如果不能满足,则直接得到结果。
代码如下:
#!/usr/bin/python
#encoding:UTF-8
#Filename:MilkShakes_Greedy.py
import sys
def preChoice(customers,flavorNum):
flag = 1
flavorCnt = flavorNum
flavorChoice = []
for i in range(flavorNum):
flavorChoice.append(-1)
for customer in customers:
if customer[0]==1:
if flavorChoice[customer[1]-1]==-1:
flavorChoice[customer[1]-1] = customer[2]
elif flavorChoice[customer[1]-1]!=customer[2]:
flag = 0
break
flavorCnt = flavorCnt - 1
return [flag,flavorCnt,flavorChoice]
def statistic(customers,choice):
flavorMalted = []
flavorUnMalted = []
for i in range(flavorNum):
flavorMalted.append(0)
flavorUnMalted.append(0)
flag = 0
for customer in customers:
for i in range(customer[0]):
j = 2 * i + 1
if choice[customer[j]-1] == customer[j+1]:
flag = 1
break
#continue
if flag!=1:
for i in range(customer[0]):
j = 2 * i + 1
if customer[j+1]==1:
flavorMalted[customer[j]-1] = flavorMalted[customer[j]-1] + 1
else:
flavorUnMalted[customer[j]-1] = flavorUnMalted[customer[j]-1] + 1
return [flavorMalted, flavorUnMalted]
def maxi(flavor):
m = max(flavor)
for i,v in enumerate(flavor):
if v==m:
return [i,v]
inname = "input.txt"
outname = "output.txt"
if len(sys.argv)>1:
inname = sys.argv[1]
outname = inname.rstrip(".in")
outname = outname + ".out"
fin = open(inname,"r")
fout = open(outname,"w")
line = fin.readline()
testCaseNum = int(line)
caseNum = 0
for caseNum in range(testCaseNum):
line = fin.readline()
flavorNum = int(line)
line = fin.readline()
customerNum = int(line)
# lines = fin.readlines(customerNum)
customers = []
# for line in lines:
# print "Case #%d:" %(caseNum+1)
# print flavorNum
# print customerNum
for i in range(customerNum):
line = fin.readline()
line = line.rstrip("\n")
customer = [int(val) for val in line.split()]
# print customer
customers.append(customer)
# print "\n"
answer = "Case #%d:" %(caseNum+1)
tpre = preChoice(customers,flavorNum)
# print tpre
flag = tpre[0]
if flag ==0:
answer = answer + " IMPOSSIBLE"
else:
flavorCnt = tpre[1]
flavorChoice = tpre[2]
while(1):
# print flavorChoice
stat = statistic(customers,flavorChoice)
flavorM = stat[0]
flavorU = stat[1]
for i in range(flavorNum):
if flavorChoice[i]!=-1:
flavorM[i] = 0
flavorU[i] = 0
# print "M:"
# print flavorM
# print "U:"
# print flavorU
mm = maxi(flavorM)
mu = maxi(flavorU)
if mm[1]==0:
for i in range(flavorNum):
if flavorChoice[i]==-1:
flavorChoice[i]=0
flag = 1
break
elif mu[1]==0:
for i in range(flavorNum):
if flavorChoice[i]==-1:
flavorChoice[i]=1
flag = 1
break
else:
if mm[0]==mu[0]:
if mm[1]>mu[1]:
flavorChoice[mm[0]] = 1
else:
flavorChoice[mm[0]] = 0
else:
flavorChoice[mu[0]] = 0
flavorCnt = flavorCnt - 1
if flavorCnt==0:
if mm[1]>0 or mu[1]>0:
flag = 0
break
if flag==1:
for val in flavorChoice:
answer = answer + " " + str(val)
else:
answer = answer + " IMPOSSIBLE"
answer = answer + "\n"
fout.write(answer)
fin.close()
fout.close()
对该程序进行测试,small case和large case都可以得到结果,不过没有百分之百的正确。
small case测试结果中,有6个结果不一致,总数是100个。large case没有标准答案,提交测试显示不正确,但不知道有多少不正确。
前面的贪心策略有些混乱,接下来继续整理。