artao

codeforces 3b之贪心算法

有货车运量V;有若干物品A 占2单位体积,有若干物品B占1单位体积;相同种类的物品价值不一定一样;

序号按照输入顺序而定;问货车可以拉走最多多少价值的物品,并输出所选物品的序号;

1)常规的解法思路:贪心,先把A填到不能填,然后再补B,补完B后再考虑用B去替换前面A,此策略必定最优;考虑到B物品的可补行!因为涉及变量较多,时刻注意A,B,空余V的数量关系;代码如下:

n,v = map(int,input().split())
l1 = []
l2 = []
for i in range(n):
    t,x = map(int,input().split())
    if t == 1:
        l1.append([x,i+1])
    else:
        l2.append([x,i+1])
l1.sort(reverse=True)
l2.sort(reverse=True)

s1 = [0]
s2 = [0]
for i in range(min(v,len(l1))):
    s1.append(s1[-1]+l1[i][0])
for i in range(min(int(v/2),len(l2))):
    s2.append(s2[-1]+l2[i][0])
ans = 0
num = 0
# print(s1)
# print(s2)
for i in range(min(v,len(l1))+1):
    # print(t)
    t = s1[i]+s2[min(len(l2),int((v-i)/2))]
    if ans < t:num,ans=i,t

print(ans)
for i in range(num):print(l1[i][1],end=' ')
for i in range(min(len(l2),int((v-num)/2))):print(l2[i][1],end=' ')

2)另外一个思路是:引入第3个因素:价值密度,不分AB只按密度大小填充。如果刚好填满,结束。否则只可能是填的最后一个是B(B0)导致超出1个体积。此时查找填充队列中的最后一个A(A0),和剩下的密度最大A(A1).

甲)A0+A1>B0:去掉B0,填入A1:相反则去掉A0.结束。

乙)A0不存在A1存在:填入A1.结束。

丙)A0存在A1不存在:比较A0和B0的价值,谁小去掉谁.结束。

丁)A0、A1都不存在:去掉B0.结束。

n,p =map(int,input().split())
a=[0]*n
for i in range(n):
   t,v=map(int,input().split())
   a[i]=(i,t,v)
a.sort(key=lambda x:x[2]/x[1],reverse=True)

ans,index,lst=0,0,[]
last1=(-1,0)
while p>0 and index<n:
   i,t,v=a[index]
   if t==1:last1=(i,v)
   p-=t
   ans+=v
   lst.append(i)
   index+=1
   
if p==-1: #p==-1 and t==2
   now=(i,v)
   while t==2 and index<n:
      i,t,v=a[index]
      index+=1
   if last1[0]>-1 and t==1: #exist 1 in lst and later
      if v+last1[1]<now[1]:#swapcase->pop last1
         ans-=last1[1]
         lst.remove(last1[0])
      else:
         ans=ans-now[1]+v
         lst.remove(now[0])
         lst.append(i)
   elif last1[0]>-1 and t==2: #exist 1 in lst only
      if last1[1]<now[1]:
         ans-=last1[1]
         lst.remove(last1[0])
      else:
         ans-=now[1]
         lst.remove(now[0])
   elif t==1 and last1[0]==-1: #exist 1 in later only
      ans=ans-now[1]+v
      lst.remove(now[0])
      lst.append(i)
   else:
      ans-=now[1]
      lst.remove(now[0])
print(ans)
for i in lst:print(i+1,end=' ')

 

posted on 2018-08-24 09:47  artao  阅读(225)  评论(0编辑  收藏  举报

导航