现在的位置: 首页 > 综合 > 正文

poj1170

2018年01月15日 ⁄ 综合 ⁄ 共 1250字 ⁄ 字号 评论关闭

【题意】

有b(<=5)种物品,每种编号为c,有k个,单价p元,现有s种组合,每种包含n种物品,给定n种物品的编号c,每种所需k,以及组合价格p

求购买所有物品所需最小费用

【输入】

第一行b

接下来b行每行三个数c、k、p

之后一行一个s

接下来s行每行描述一个组合

【输出】

最小费用

b和s很小,所以状态压缩一下,记忆化搜一下就行

program poj1170;
var
  s,c,b,n,i,j,k:longint;
  six:array [0..7] of longint;
  num:array [0..1000] of longint;
  left,pri:array [0..6] of longint;
  p:array [0..99] of longint;
  com:array [0..99,0..6] of longint;
  f:array [0..7777] of longint;
  yes:array [0..7777] of boolean;

function min (a,b:longint):longint;inline;
begin
  if a<b then exit(a)
         else exit(b);
end;

function search (status:longint):longint;
var
  i,j,k:longint;
begin
  if yes[status] then exit(f[status]);
  f[status]:=maxlongint;
  for i:=1 to s do
    begin
      k:=status;
      for j:=1 to b do
        if status div six[j-1] mod 6>=com[i,j] then k:=k-com[i,j]*six[j-1]
                                               else break;
      if status div six[j-1] mod 6<com[i,j] then continue;
      f[status]:=min(f[status],search(k)+p[i]);
    end;
  for i:=1 to b do
    if status div six[i-1] mod 6>0 then
      f[status]:=min(f[status],search(status-six[i-1])+pri[i]);
  yes[status]:=true;
  exit(f[status]);
end;

begin
  read(b);
  for i:=1 to b do
    begin
      read(c,left[i],pri[i]);
      num[c]:=i;
    end;
  read(s);
  for i:=1 to s do
    begin
      read(n);
      for j:=1 to n do
        begin
          read(c,k);
          com[i,num[c]]:=com[i,num[c]]+k;
        end;
      read(p[i]);
    end;
  six[0]:=1;
  for i:=1 to 7 do
    six[i]:=six[i-1]*6;
  k:=0;
  for i:=1 to b do
    k:=k+left[i]*six[i-1];
  fillchar(yes,sizeof(yes),false);
  yes[0]:=true;
  f[0]:=0;
  writeln(search(k));
end.
【上篇】
【下篇】

抱歉!评论已关闭.