|
终于弄出来了 告别NOI........ 高三努力...... 大致思路:把zj个主件和m-zj个附件打成num个包,f[i,j]表示处理完前i个主件还剩j元时获得的最大权值 占用内存2232KB - // program NOIP2006_2:Budget
- // by bj4sj
- const
- maxn=3500;
- maxm=60;
- var
- v,w,p:array[1..maxm] of integer;
- son:array[1..maxm,1..2] of integer;
- fq,jg,qz:array[1..maxm] of integer;
- i,zj,num,numm,m:integer;
- N,max:integer;
- f:array[0..4*maxm,0..maxn] of integer;
- procedure init;//输入数据,并转化数据,成为背包问题
- var
- i,j,k:integer;
- begin
- assign(input,'budget.in');
- reset(input);
- read(N,m);
- n:=n div 10;
- zj:=0;
- for i:=1 to m do
- begin
- read(v[i],w[i],fq[i]);
- v[i]:=v[i] div 10;
- if fq[i]=0 then
- begin
- inc(zj);//主件个数
- son[zj,1]:=-1;//儿子编号指针
- son[zj,2]:=-1;
- p[zj]:=i;//主件编号指针
- end
- else
- begin
- for k:=1 to zj do if p[k]=fq[i] then fq[i]:=k;
- if son[fq[i],1]=-1 then son[fq[i],1]:=i else son[fq[i],2]:=i;
- end;
- end;
- num:=0;
- for i:=1 to zj do
- begin
- inc(num);
- qz[num]:=v[p[i]]*w[p[i]]; //第num个包的权值(只含主件)
- jg[num]:=v[p[i]]; //价格
- for k:=1 to 2 do
- begin
- if son[i,k]<>-1 then
- begin
- inc(num);
- qz[num]:=v[p[i]]*w[p[i]]+v[son[i,k]]*w[son[i,k]]; //第num个包的权值(含主件和第K个附件)
- jg[num]:=v[p[i]]+v[son[i,k]];
- end;
- end;
- if son[i,2]<>-1 then
- begin
- inc(num);
- qz[num]:=v[p[i]]*w[p[i]]+v[son[i,1]]*w[son[i,1]]+v[son[i,2]]*w[son[i,2]];//第num个包的权值(含主件和2个附件)
- jg[num]:=v[p[i]]+v[son[i,1]]+v[son[i,2]];
- end;
- end;
- close(input);
- end;
- procedure slove;
- var
- i,j,k:integer;
- tmp:array[1..6] of integer;
- begin
- for i:=0 to 4*maxm do
- for j:=0 to maxn do f[i,j]:=-20000;
- for j:=0 to n do f[0,j]:=0;
- num:=0;
- for i:=1 to zj do //解决背包问题,每个主件只能选一次.究竟选哪个则需要看tmp[1..6]的大小
- begin
- for j:=0 to N do
- begin
- numm:=num;
- for k:=4 to 6 do tmp[k]:=-20000;
- tmp[1]:=f[i-1,j];
- tmp[2]:=f[i,j];
- inc(num);
- tmp[3]:=f[i-1,j+jg[num]]+qz[num];
- if son[i,1]<>-1 then
- begin
- inc(num);
- tmp[4]:=f[i-1,j+jg[num]]+qz[num];
- end;
- if son[i,2]<>-1 then
- begin
- inc(num);
- tmp[5]:=f[i-1,j+jg[num]]+qz[num];
- inc(num);
- tmp[6]:=f[i-1,j+jg[num]]+qz[num];
- end;
- max:=-20000;
- for k:=1 to 6 do
- begin
- if max<tmp[k] then max:=tmp[k];
- end;
- f[i,j]:=max;
- if j<>n then num:=numm;
- end;
- end;
- end;
- begin
- init;
- slove;
- max:=-20000;
- for i:=0 to n do
- begin
- if max<f[zj,i] then max:=f[zj,i];
- end;
- assign(output,'budget.out');
- rewrite(output);
- writeln(max*10:1);
- close(output);
- end.
[ 此贴被bj4sj在2006-11-20 01:25重新编辑 ]
|