• 01背包


    【题目描述】

           有一个容量为W的背包,有N种物品,第i种物品的体积为Ti,价值为Vi

           对于每种物品,你可以选择是否将它放入背包,放入背包的物品的总体积不能超过W,在这个前提下你希望放入背包的物品的总价值最大。

    【输入数据】

           第一行两个数W,N,表示背包的容量和物品的数量。

           之后N行,每行两个数Ti,Vi,表示第i件物品的体积和价值。

    【输出数据】

           输出一个数,放入背包的物品的最大总价值。

    【样例】

    bag.in

    bag.out

    9 3

    7 14

    5 9

    4 7

    16

    【数据规模】

    前边30%的数据:   n≤20    w≤100000000  3个数据;

    中间40%的数据:   n≤300   w≤100000000  6个数据;

    后面30%的数据:   300<n≤1000  w≤10000  3个数据。

    【数据提示】

    数据保证随机。

    题目分析:

      题意简单,好像是动规中的01背包问题。

    01背包的时间复杂度O(nV)或者O(nw),这样好像只能得30分。

    怎么办呢?题目中好像只有n比较小,能不能想办法从n下手?

    没有别的办法就搜吧,注意加上搜索的优化和卡时。

    首先预处理数据

    (1)按性价比从高到底的顺序对物品排序;

    (2)贪心求出最大值;

    (3)求后i项的价值总和,搜索优化用;

    (4)求后i项最小的体积,搜索优化用。

    搜索:

        为了防止超时,要记录搜索运行的次数,当次数<=50000000时,可以继续搜,否则果断结束,输出当前结果

    var v,w,sumv,minw:array[1..1000]of int64;
        f:array[0..10000]of int64;
        m,n,i,j,ans,nowmax,tot:longint;//time,ttime:double;
    
    procedure init;
    var i:longint;
    begin
      assign(input,'bag.in');reset(input);
      assign(output,'bag.out');rewrite(output);
      readln(m,n);
      for i:=1 to n do begin
        readln(w[i],v[i]);
      end;
      
    end;
    
    procedure qsort(l,r:longint);//按性价比从高到低排序
    var i,j,t:longint;x:double;
    begin
      i:=l;j:=r;x:=v[(l+r) shr 1]/w[(l+r) shr 1];
      repeat
        while v[i]/w[i]>x+1e-7 do inc(i);
        while v[j]/w[j]<x-1e-7 do dec(j);
        if i<=j then begin
          t:=w[i];w[i]:=w[j];w[j]:=t;t:=v[i];v[i]:=v[j];v[j]:=t;
          inc(i);dec(j);
        end;
      until i>j;
      if j>l then qsort(l,j);if i<r then qsort(i,r);
    end;
    
    function min(a,b:longint):longint;
    begin if a<b then exit(a) else exit(b) end;
    
    function max(a,b:longint):longint;
    begin if a>b then exit(a) else exit(b) end;
    
    procedure dfs_predeal;
    var i,t:longint;
    begin
      qsort(1,n);
      i:=0;t:=m;ans:=0;nowmax:=0;tot:=0;
      for i:=1 to n do if w[i]<=t then begin
        dec(t,w[i]);inc(ans,v[i]);
      end;//贪心法求得最大值
      for i:=n downto 1 do sumv[i]:=sumv[i+1]+v[i];{//求后i项的价值总和,搜索优化用}
      minw[n+1]:=maxlongint;
      for i:=n downto 1 do minw[i]:=min(minw[i+1],w[i]);{求后i项最小的体积,搜索优化用}
    end;
    
    procedure dfs(i,mm:longint);//考虑第i件物品,当前剩余体积为mm
    begin
      if minw[i]>mm then begin//如果后i件物品中最小的体积都大于mm
        if nowmax>ans then ans:=nowmax;
        exit;
      end;
      if nowmax+sumv[i]<=ans then exit;{如果加上剩余i件物品的价值总和,还小于当前的最优值}
      inc(tot);if tot>50000000 then begin
        writeln(ans);close(output);halt;
      end;
      if mm>=w[i] then begin
        inc(nowmax,v[i]);//选第i件物品
        dfs(i+1,mm-w[i]);
        dec(nowmax,v[i]);//回溯
      end;
      dfs(i+1,mm);
    end;
    
    procedure dp;
    begin
      fillchar(f,sizeof(f),0);
      for i:=1 to n do
        for j:=m downto w[i] do
          f[j]:=max(f[j],f[j-w[i]]+v[i]);
      ans:=f[m];
    end;
    
    begin
      init;
      if (m>10000) then begin
        dfs_predeal;
        dfs(1,m);
      end else dp;
      writeln(ans);
      close(output);
    end.
    View Code
  • 相关阅读:
    PowerDesigner学习 ---- 系列文章
    PowerDesigner基础使用 ---- 入门学习
    PowerDesigner ---- 数据库设计(概念模型CDM和物理模型PDM)
    PowerDesigner V16.5 安装及汉化
    在树莓派是安装并配置NTP服务
    RESTful Web API 理解
    Linux或树莓派3——挂载U盘、移动硬盘并设置rwx权限
    开启树莓派自带的VNC功能
    c#代码获取web.config配置文件里面设置的 <compilation debug="true"节点
    WebService的web客户端同步、异步、多线程向服务端传入参数的数据交互方式
  • 原文地址:https://www.cnblogs.com/ssfzmfy/p/4033205.html
Copyright © 2020-2023  润新知