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没有标准答案,提交测试显示不正确,但不知道有多少不正确。

前面的贪心策略有些混乱,接下来继续整理。

posted @ 2012-04-06 21:18  Frandy.CH  阅读(322)  评论(0编辑  收藏  举报