noip2006-金明2008.11.5

noip2006-金明2008.11.5

问题:1.把主件单独拿出来,改变了原来的编号,反而跟难处理

我在存储的时候,把附件剔除出去了,一直wa,后来,看了别人的,他们在读入附件的时候,直接加在主见的后边,应当存放附件的那个编号是空的,这样号码就不会乱了。我是把主见单独挑出来,存在一个数组里,这样初始号码就很乱,对数据的处理就不是太容易。实际上,把附件站的那个编号,都赋值为0,dp时当然不会影响结果,反倒是我把编号变了更难处理。

2.编号时顺次编的,不论是主件还是附件,都有编号,不是只有主件才有编号,做特是要格外注意这一点。

Program1:打乱编号的wa

program p_budget;
const fin='budget.in';fout='budget.out';
var f1,f2:text;
       lu,v,m,n,i,j,k:longint;
       {v:钱;m输入的件数;n:主件的个数}
       a:array[1..60,1..2]of longint;{zhujian}
       u:array[1..60,1..3]of longint;
       d:array[1..60]of longint;
       b:array[1..60,1..2,1..2]of longint;{fujian}
       {       主件编号,附件号,1:价格,2:重要度}
       c:array[1..60]of longint;
       f:array[0..3200]of longint;
procedure init;
var i,x1,x2,x3:longint;
begin
     fillchar(b,sizeof(b),0);k:=0;lu:=0;
     n:=0;fillchar(c,sizeof(c),0);

     read(v,m);v:=v div 10;
     for i:=1 to m do
        begin read(x1,x2,x3);
          x1:=x1 div 10;
             if x3=0 then
                       begin inc(n);d[n]:=i;a[n,1]:=x1;a[n,2]:=x2;end
                   else begin
                   inc(lu);u[lu,1]:=x1;u[lu,2]:=x2;u[lu,3]:=x3;end;
       end;
                       for i:=1 to lu do
                     begin
                       k:=0;repeat inc(k);until d[k]=u[i,3];
                       inc(c[k]);
                       b[k,c[k],1]:=u[i,1];b[k,c[k],2]:=u[i,2];
                       end;//这里打乱了编号,实际上,不重新编号,对结果,运行时间的影响并不大
 {for i:=1 to n do
  begin writeln('-------------------',i,'-----------------',d[i]);
        write(a[i,1],' ',a[i,2],'         ',b[i,1,1],' ',b[i,1,2],'      ',b[i,2,1],' ',b[i,2,2]);
        writeln;
        end;}
end;
 procedure doit;
var i,j,ans:longint;
begin fillchar(f,sizeof(f),0);
   for i:=1 to n do
     for j:=v downto 0 do
        begin
           if (j-a[i,1]>=0) and ((f[j-a[i,1]]+a[i,2]*a[i,1])>f[j]) then f[j]:=f[j-a[i,1]]+a[i,2]*a[i,1];
           if (j-a[i,1]-b[i,1,1]>=0) and ((f[j-a[i,1]-b[i,1,1]]+a[i,2]*a[i,1]+b[i,1,1]*b[i,1,2])>f[j]) then
                  f[j]:=f[j-a[i,1]-b[1,1,1]]+a[i,2]*a[i,1]+b[i,1,1]*b[i,1,2];
            if (j-a[i,1]-b[i,2,1]>=0)  and ((f[j-a[i,1]-b[i,2,1]]+a[i,2]*a[i,1]+b[i,2,1]*b[i,2,2])>f[j]) then
                  f[j]:=f[j-a[i,1]-b[1,2,1]]+a[i,2]*a[i,1]+b[i,2,1]*b[i,2,2];
           if (j-a[i,1]-b[i,1,1]-b[i,2,1]>=0) and ((f[j-a[i,1]-b[i,1,1]-b[i,2,1]]+a[i,1]*a[i,2]+b[i,1,1]*b[i,1,2]+b[i,2,1]*b[i,2,2])>f[j]) then
                  f[j]:=f[j-a[i,1]-b[i,1,1]-b[i,2,1]]+a[i,1]*a[i,2]+b[i,1,1]*b[i,1,2]+b[i,2,1]*b[i,2,2];
       end;
       ans:=0;
for i:=1 to v do
begin
  if f[i]>ans then ans:=f[i];
  end;
  write(ans*10);
end;
begin init; doit;end.

Program 2 :心得:在dp前,要对数据进行最好的处理,使得在dp时,尽量少的计算。本题先计算出了每件物品的值,避免了重复的计算。

type
	sz=record
		x:longint;
		v,w:array[0..60] of longint;
	    end;
var
	a:array[0..60] of sz;
	i,j,k,n,m,v,p,q,max:longint;
	f:array[0..10000] of longint;
begin
    assign(input,'budget.in');reset(input);
assign(output,'budget.out');rewrite(output);
	readln(n,m); n:=n div 10; j:=0;
	for i:=1 to m do begin
		readln(v,p,q);
                v:=v div 10; p:=p*v;//直接算出重要度和价格的积,避免以后重复计算
		if q=0 then begin
	        	a[i].v[0]:=v;
			a[i].w[0]:=p;
			inc(k);
		end
	        else
		begin
            inc(a[q].x);
			a[q].v[a[q].x]:=v;
			a[q].w[a[q].x]:=p;
		end;
	end;
        for i:=1 to m do
		for j:=n downto 0 do begin
			if (j-a[i].v[0]>=0)and(f[j-a[i].v[0]]+a[i].w[0]>f[j]) then  
f[j]:=f[j-a[i].v[0]]+a[i].w[0];
                        if (j-a[i].v[0]-a[i].v[1]>=0)and(f[j-a[i].v[0]-a[i].v[1]]+a[i].w[0]+a[i].w[1]>f[j]) then
			f[j]:=f[j-a[i].v[0]-a[i].v[1]]+a[i].w[0]+a[i].w[1];
			if (j-a[i].v[0]-a[i].v[2]>=0)and
				(f[j-a[i].v[0]-a[i].v[2]]+a[i].w[0]+a[i].w[2]>f[j]) then
			f[j]:=f[j-a[i].v[0]-a[i].v[2]]+a[i].w[0]+a[i].w[2];
			if (j-a[i].v[0]-a[i].v[1]-a[i].v[2]>=0)and
				 
(f[j-a[i].v[0]-a[i].v[1]-a[i].v[2]]+a[i].w[0]+a[i].w[1]+a[i].w[2]>f[j]) then
			f[j]:=f[j-a[i].v[0]-a[i].v[1]-a[i].v[2]]+a[i].w[0]+a[i].w[1]+a[i].w[2];
			end;
	max:=0;
	for i:=1 to n do if f[i]>max then max:=f[i];
	writeln(max*10);
close(input);close(output);
end.


  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值