当前位置: 首页 > wzjs >正文

北京企业建设网站制作网站优化方式有哪些

北京企业建设网站制作,网站优化方式有哪些,动漫网页设计作品欣赏,在线logo制作生成免费文章目录 背包DP01 背包完全背包多重背包二进制优化单调队列优化 小结 背包DP 背包 DP,说白了就是往一个背包里扔东西,求最后的最大价值是多少,一般分为了三种:01 背包、完全背包和多重背包。而 01 背包则是一切的基础。 01 背包…

文章目录

  • 背包DP
    • 01 背包
    • 完全背包
    • 多重背包
      • 二进制优化
      • 单调队列优化
  • 小结

背包DP

背包 DP,说白了就是往一个背包里扔东西,求最后的最大价值是多少,一般分为了三种:01 背包、完全背包和多重背包。而 01 背包则是一切的基础。

01 背包

特点:每个物品只有一个,只能选择装这个物品或者不装。

这时我们一般设一个 dp[i][j] 表示前 i i i 个物品再总体积为 j j j 的情况下装的最大价值是多少。所以 01 背包的时间复杂度为 O ( n 2 ) O(n^2) O(n2),这时我们可以得到这样一个状态转移方程:

d p i , j = max ⁡ { d p i − 1 , j , d p i − 1 , j − v i + w i } dp_{i,j}=\max\{dp_{i-1,j},dp_{i-1,j-v_i}+w_i\} dpi,j=max{dpi1,j,dpi1,jvi+wi}

这里的 v i v_i vi 指当前物品所占的体积, w i w_i wi 指当前物品的价值。

那这是怎么一回事呢?我们可以这样想:我要么不选这件物品,那么总价值就和 d p i − 1 , j dp_{i-1,j} dpi1,j 一样(即同样的体积在前 i − 1 i-1 i1 件物品中的最大价值),如果选了,那就和前 i − 1 i-1 i1 件物品在体积为 j − v i j-v_i jvi 的情况下的最大价值再加上当前物品的价值 w i w_i wi 一样,那再取其中的最大值就行了。

但是,我们会发现一个问题:如果你的总体积为 V V V,总物品数为 n n n,那你的空间复杂度就是 O ( V n ) O(Vn) O(Vn),这可是一个极其庞大的数字,这是我们就要请上我们的滚动背包!

滚动背包旨在通过观察状态转移方程看看哪些空间没用从而可以省掉。比如说上面的状态转移方程,我们会发现 DP 的第一维只与当前状态与上一状态有关,而与其他的无关,所以其它空间就是被浪费了的,所以我们只需要把第一维开个 2 2 2,而不用开 n n n,这样,空间复杂度就被压到了 O ( 2 V ) O(2V) O(2V),状态转移方程也就变成了这样:

d p i m o d 2 , j = max ⁡ { d p ( i − 1 ) m o d 2 , j , d p ( i − 1 ) m o d 2 , j − v i + w i } dp_{i\bmod2,j}=\max\{dp_{(i-1)\bmod2,j},dp_{(i-1)\bmod2,j-v_i}+w_i\} dpimod2,j=max{dp(i1)mod2,j,dp(i1)mod2,jvi+wi}

上面这种方法适用于初学者,因为它清楚直观、浅显易懂。

让我们先来看一道例题:

N N N 件物品和一个容量是 V V V 的背包。每件物品只能使用一次。

i i i 件物品的体积是 v i v_i vi,价值是 w i w_i wi

求解将哪些物品装入背包,可使这些物品的总体积不超过背包容量,且总价值最大。

输出最大价值。

很经典的一道 01 背包问题,直接用上面的公式就对了。

代码:

#include<bits/stdc++.h>
#define int long long
using namespace std;
int n,vv,v[1006],w[1006],dp[2][1006]; 
signed main()
{cin>>n>>vv;for(int i=1;i<=n;i++){cin>>v[i]>>w[i];}for(int i=1;i<=n;i++){for(int j=0;j<=vv;j++){dp[i%2][j]=dp[(i-1)%2][j];if(j>=v[i]){dp[i%2][j]=max(dp[(i-1)%2][j],dp[(i-1)%2][j-v[i]]+w[i]);}}}cout<<dp[n%2][vv];return 0;
}

当然,我们也可以在这个的基础上优化成一维滚动背包,但是中间的循环需要颠倒过来一下,具体我们可以这么想:我们上面的状态转移方程再更新时原本的和现在的状态是不会受影响的,而如果我们正着循环,可能就会出现这种情况:

按照我们之前的状态转移方程,我们应该拿原本的旧的状态来更新新的状态,但现在我们却拿我们计算好了的新的状态来更新更新的状态,这是完全不符合的,而倒过来循环正好就能避免这种事情的发生。(想通了的同学继续看,没想通的同学抠破脑袋想。)

所以上面的代码还可以写成这样:

#include<bits/stdc++.h>
#define int long long
using namespace std;
int n,vv,v[1006],w[1006],dp[1006]; 
int main()
{cin>>n>>vv;for(int i=1;i<=n;i++){cin>>v[i]>>w[i];}for(int i=1;i<=n;i++){for(int j=vv;j>=v[i];j--){dp[j]=max(dp[j],dp[j-v[i]]+w[i]);}}cout<<dp[vv];return 0;
}

完全背包

特点:每个物体有无穷多个,可以无限取同一个物品。

这时的改动很小,只需要把上面 01 背包优化成一维时的循环改成正着循环就行了。这又是为啥呢?

我们前面不是说了吗:正着循环会把更新好的状态拿去更新当前状态。如果是 01 背包每种只能用一次,那肯定不行。但是完全背包可以多次放一个物品啊,当前的最新状态对于另一个状态来讲可能只是一个旧状态罢了。

所以,我们把上面的代码稍作改动:

#include<bits/stdc++.h>
#define int long long
using namespace std;
int n,vv,v[1006],w[1006],dp[1006]; 
int main()
{cin>>n>>vv;for(int i=1;i<=n;i++){cin>>v[i]>>w[i];}for(int i=1;i<=n;i++){for(int j=v[i];j<=vv;j++){dp[j]=max(dp[j],dp[j-v[i]]+w[i]);}}cout<<dp[vv];return 0;
}

就水灵灵的 A C \color{green}{AC} AC 了!

(讲的稍微有点快,没看懂的同学可以回去再看。)

多重背包

特点:每件物品有一定数量,所装的物品数量不能超过这个值。

还是拿一道例题讲一下:

N N N 种物品和一个容量是 V V V 的背包。第 i i i 种物品最多有 s i s_i si 件,每件体积是 v i v_i vi,价值是 w i w_i wi
求解将哪些物品装入背包,可使物品体积总和不超过背包容量,且价值总和最大。
输出最大价值。

外面两层循环跟 01 背包一模一样,但是因为有数量限制,里面需要多加一层循环:

for(int k=0;k<=s[i]&&v[i]*k<=j;k++)

这层循环就是循环你要拿或者是不拿 k k k 个物品。

然后我们写状态转移方程:

d p i , j = max ⁡ { d p i − 1 , j , d p i − 1 , j − k × v i + k × w i } dp_{i,j}=\max\{dp_{i-1,j},dp_{i-1,j-k\times v_i}+k\times w_i\} dpi,j=max{dpi1,j,dpi1,jk×vi+k×wi}

再根据与 01 背包一样的套路优化一下即可。

代码如下:

#include<bits/stdc++.h>
#define int long long
using namespace std;
int n,vv,v[106],w[106],s[106],dp[106]; 
signed main()
{cin>>n>>vv;for(int i=1;i<=n;i++){cin>>v[i]>>w[i]>>s[i];}for(int i=1;i<=n;i++){for(int j=vv;j>=v[i];j--){for(int k=0;k<=s[i]&&v[i]*k<=j;k++){dp[j]=max(dp[j],dp[j-v[i]*k]+w[i]*k);}}}cout<<dp[vv];return 0;
}

二进制优化

但是(一般一切顺利的时候搜会有个“但是”),我们稍加计算发现它的时间复杂度达到了恐怖的 O ( V × ∑ s i ) O(V\times\sum s_i) O(V×si),这个时间复杂度是极高的,为了降低时间复杂度,我们采取了一种优化:转为 01 背包问题。

因为我们有至多 s i s_i si 个,那么我们可以选择的个数有哪些呢?这时,聪明的计算机学家们就想到了一种办法:转二进制

这个转二进制有什么好处呢?好处可大了去了。因为我们知道任何一个数倍拆成二进制后是可以拼凑出再 s i s_i si 以内的所有数的,而对于当前这个数加不加上又是一个 01 背包问题。

也就是这样:假设 s i = 7 s_i=7 si=7,那么 7 7 7 写成二进制就是 111 111 111,拆成二的幂次相加就是 2 2 + 2 1 + 2 0 2^2+2^1+2^0 22+21+20,而对于每一个数选不选进来凑成一个小于 s i s_i si 的数是个 01 背包问题。于是我们就将多重背包转化成了 01 背包。而对于每一个数再乘 v i v_i vi 表示新的体积,乘 w i w_i wi 表示新的质量,然后做 01 背包就行。

这样我们就将时间复杂度降到了 O ( V × ∑ log ⁡ 2 ( s i ) ) O(V\times\sum\log_2(s_i)) O(V×log2(si)),大大优化了啊!

代码:

#include<bits/stdc++.h>
#define int long long
using namespace std;
struct binary{int v,w;
};
int n,vv,v[1006],w[1006],s[1006],dp[2006]; 
vector<binary>v1;
signed main()
{cin>>n>>vv;for(int i=1;i<=n;i++){cin>>v[i]>>w[i]>>s[i];}for(int i=1;i<=n;i++){for(int j=1;j<=s[i];j*=2){s[i]-=j;v1.push_back({v[i]*j,w[i]*j});}if(s[i]>=0){v1.push_back({v[i]*s[i],w[i]*s[i]});}}for(auto i:v1){for(int j=vv;j>=i.v;j--){dp[j]=max(dp[j],dp[j-i.v]+i.w);}}cout<<dp[vv];return 0;
}

单调队列优化

注:一般情况下只会卡到二进制优化,所以单调队列优化看不懂的同学可以直接跳过。

二进制优化已经很好了,但还不是最好,真正好的直接优化到了 O ( N × V ) O(N\times V) O(N×V),让我们有请单调队列优化

~~由于本作者实在是太菜了,竟然没看懂单调队列优化,~~感兴趣的同学可以参考这篇文章。

小结

这篇文章带你梳理了三种基本背包:01 背包、完全背包与多重背包,至于更多的背包模型请大家搜索背包九讲,那里有更多的大佬在等着你们。

http://www.dtcms.com/wzjs/125932.html

相关文章:

  • 阿里云虚拟主机可以做几个网站吗今天重大新闻头条新闻军事
  • 网站开发验收报告模板怎么提高百度关键词排名
  • 做网站的的价格系统优化软件有哪些
  • 松原做公司网站从事网络营销的公司
  • 网站开发jd怎么自己找外贸订单
  • 建设部网站黑臭水体公布中级经济师考试
  • 精美合同网站建设网络营销推广策划方案
  • 广州做网站多少钱怎样做app推广
  • 装修网站实景图vr怎么做的广告竞价
  • 如何查公司网站谁家做的活动营销
  • shopify可以做企业网站嘛西安关键词seo
  • 网站优化 检测响应速度seo运营推广
  • 网站建设维护专员岗位说明seo属于什么
  • 成都网站制作公司有哪些营销案例100例小故事及感悟
  • 安徽鲁班建设集团网站广告推广精准引流
  • 大型平面设计网站营销推广技巧
  • 提供网站建设找哪家公司好金华关键词优化平台
  • 网站建设属于软件开发每日新闻摘要30条
  • 宝钢工程建设有限公司网站seo排名的方法
  • 北京如何做网站营销网站系统
  • wordpress+做仿站百度账号注册入口
  • 网站制作 合同kol推广是什么意思
  • 苹果软件下载网站seo搜索引擎优化原理
  • 怎么给网站加图标营销渠道策略有哪些
  • 武夷山网站推广服务企业邮箱如何申请注册
  • 做民宿的网站英文谷歌seo
  • 国外搜索网站建设百度云引擎搜索
  • 用asp做网站怎么美观b站是哪个网站
  • 网站优化公司哪个好网推平台
  • 上海昆山网站公司制作一个网站的费用是多少