背包问题的求解:
#include
using namespace std;
struct bag{
double w;
double p;
double p_w;
int order;
}; //说明物品特性
void sort(struct bag *a,int low,int high);
int main()
{
int n,i;
double *x; //解向量,由于书数组,拿指针表示
double m,cost=0;
struct bag *b; //结构数组,用于表示所有物品
//定义文件流并与具体的磁盘文件相关联
ifstream fin;
fin.open("背包问题_in.txt");
ofstream fout;
fout.open("背包问题_out.txt");
//输入物品数目 n 背包容量 M
fin>>n>>m;
//动态分配存储空间
b=new struct bag[n];
x=new double[n];
for(i=0;i<n;i++){
fin>>b[i].w>>b[i].p; //输入物品重量和运价
b[i].p_w=b[i].p/b[i].w; //求出运价重量比
b[i].order=i; //贴标签
}
sort(b,0,n-1); //按运价重量比从大到小进行排序
for(i=0;i<n;i++)
x[i]=0; //初始化解向量
for(i=0;i<n;i++) //处理所有物品
if(b[i].w<=m){ //若背包能放得下整个物品
x[b[i].order]=1; //放入背包
m-=b[i].w; //背包剩余容量减小
cost+=b[i].p; //总价值增加
}
else{ //否则,放不下整个物品
x[b[i].order]=m/b[i].w; //放一部分
cost+=x[b[i].order]*b[i].p; //总价值增加
break; //打断,后续物品由于不能放入背包,不需处理
}
for(i=0;i<n;i++)
fout<<x[i]<<""; //输出解向量
fout<<endl<<cost;
//删除动态分配下的空间
delete []x;
delete []b;
//关闭文件指针
fin.close();
fout.close();
return 0;
}
int par(struct bag *a,int low,int high)
{
struct bag temp;
temp=a[low];
double t;
t=a[low].p_w;
while(low<high){
while(low<high && a[high].p_w<=t)
--high;
a[low]=a[high];
while(low=t)
++low;
a[high]=a[low];
}
a[low]=temp;
return low;
}
void sort(struct bag *a,int low,int high)
{
int loc;
if(low<high){
loc=par(a,low,high);
sort(a,low,loc-1);
sort(a,loc+1,high);
}
}
...=。=
这个可掰的真够细的..
太细了反而对你没好处,算法这东西是要靠自己去多想的!
多做题,多思考。你是搞OI的不?看过DD大牛的背包九讲没有?
你要先搞清基础的,搞清思路。至于实现,不要轻易去看别人的代码,要自己写。要是实在写不出来,才去看。当然至于什么程度叫做实在写不出来,就要看你对自己的严格程度了。
我记得我当初的时候是坐车吃饭都在理解思路,想实现方式。
用登山算法求解背包问题 function []=DengShan(n,G,P,W) %n是背包的个数,G是背包的总容量,P是价值向量,W是物体的重量向量 %n=3;G=20;P=[25,24,15];W2=[18,15,10];%输入量 W2=W; [Y,I]=sort(-P./W2);W1=[];X=[];X1=[]; for i=1:length(I) W1(i)=W2(I(i)); end W=W1; for i=1:n X(i)=0; RES=G;%背包的剩余容量 j=1; while W(j)<=RES X(j)=1; RES=RES-W(j); j=j+1; end X(j)=RES/W(j); end for i=1:length(I) X1(I(i))=X(i); end X=X1; disp('装包的方法是');disp(X);disp(X.*W2);disp('总的价值是:');disp(P*X');
时间复杂度是非指数的
2)递归法
先看完全背包问题
一个旅行者有一个最多能用m公斤的背包,现在有n种物品,每件的重量分别是W1,W2,...,Wn,
每件的价值分别为C1,C2,...,Cn.若的每种物品的件数足够多.
求旅行者能获得的最大总价值。
本问题的数学模型如下:
设 f(x)表示重量不超过x公斤的最大价值,
则 f(x)=max{f(x-i)+c[i]} 当x>=w[i] 1<=i<=n
可使用递归法解决问题程序如下:
program knapsack04;
const maxm=200;maxn=30;
type ar=array[0..maxn] of integer;
var m,n,j,i,t:integer;
c,w:ar;
function f(x:integer):integer;
var i,t,m:integer;
begin
if x=0 then f:=0 else
begin
t:=-1;
for i:=1 to n do
begin
if x>=w[i] then m:=f(x-i)+c[i];
if m>t then t:=m;
end;
f:=t;
end;
end;
begin
readln(m,n);
for i:= 1 to n do
readln(w[i],c[i]);
writeln(f(m));
end.
说明:当m不大时,编程很简单,但当m较大时,容易超时.
4.2 改进的递归法
改进的的递归法的思想还是以空间换时间,这只要将递归函数计算过程中的各个子函数的值保存起来,开辟一个
一维数组即可
程序如下:
program knapsack04;
const maxm=2000;maxn=30;
type ar=array[0..maxn] of integer;
var m,n,j,i,t:integer;
c,w:ar;
p:array[0..maxm] of integer;
function f(x:integer):integer;
var i,t,m:integer;
begin
if p[x]<>-1 then f:=p[x]
else
begin
if x=0 then p[x]:=0 else
begin
t:=-1;
for i:=1 to n do
begin
if x>=w[i] then m:=f(i-w[i])+c[i];
if m>t then t:=m;
end;
p[x]:=t;
end;
f:=p[x];
end;
end;
begin
readln(m,n);
for i:= 1 to n do
readln(w[i],c[i]);
fillchar(p,sizeof(p),-1);
writeln(f(m));
end.
3)贪婪算法
改进的背包问题:给定一个超递增序列和一个背包的容量,然后在超递增序列中选(只能选一次)或不选每一个数值,使得选中的数值的和正好等于背包的容量。
代码思路:从最大的元素开始遍历超递增序列中的每个元素,若背包还有大于或等于当前元素值的空间,则放入,然后继续判断下一个元素;若背包剩余空间小于当前元素值,则判断下一个元素
简单模拟如下:
#define K 10
#define N 10
#i nclude <stdlib.h>
#i nclude <conio.h>
void create(long array[],int n,int k)
{/*产生超递增序列*/
int i,j;
array[0]=1;
for(i=1;i<n;i++)
{
long t=0;
for(j=0;j<i;j++)
t=t+array[j];
array[i]=t+random(k)+1;
}
}
void output(long array[],int n)
{/*输出当前的超递增序列*/
int i;
for(i=0;i<n;i++)
{
if(i%5==0)
printf("\n");
printf("%14ld",array[i]);
}
}
void beibao(long array[],int cankao[],long value,int count)
{/*背包问题求解*/
int i;
long r=value;
for(i=count-1;i>=0;i--)/*遍历超递增序列中的每个元素*/
{
if(r>=array[i])/*如果当前元素还可以放入背包,即背包剩余空间还大于当前元素*/
{
r=r-array[i];
cankao[i]=1;
}
else/*背包剩余空间小于当前元素值*/
cankao[i]=0;
}
}
void main()
{
long array[N];
int cankao[N]={0};
int i;
long value,value1=0;
clrscr();
create(array,N,K);
output(array,N);
printf("\nInput the value of beibao:\n");
scanf("%ld",&value);
beibao(array,cankao,value,N);
for(i=0;i<N;i++)/*所有已经选中的元素之和*/
if(cankao[i]==1)
value1+=array[i];
if(value==value1)
{
printf("\nWe have got a solution,that is:\n");
for(i=0;i<N;i++)
if(cankao[i]==1)
{
if(i%5==0)
printf("\n");
printf("%13ld",array[i]);
}
}
else
printf("\nSorry.We have not got a solution.\n");
}
贪婪算法的另一种写法,beibao函数是以前的代码,用来比较两种算法:
#define K 10
#define N 10
#i nclude <stdlib.h>
#i nclude <conio.h>
void create(long array[],int n,int k)
{
int i,j;
array[0]=1;
for(i=1;i<n;i++)
{
long t=0;
for(j=0;j<i;j++)
t=t+array[j];
array[i]=t+random(k)+1;
}
}
void output(long array[],int n)
{
int i;
for(i=0;i<n;i++)
{
if(i%5==0)
printf("\n");
printf("%14ld",array[i]);
}
}
void beibao(long array[],int cankao[],long value,int count)
{
int i;
long r=value;
for(i=count-1;i>=0;i--)
{
if(r>=array[i])
{
r=r-array[i];
cankao[i]=1;
}
else
cankao[i]=0;
}
}
int beibao1(long array[],int cankao[],long value,int n)
{/*贪婪算法*/
int i;
long value1=0;
for(i=n-1;i>=0;i--)/*先放大的物体,再考虑小的物体*/
if((value1+array[i])<=value)/*如果当前物体可以放入*/
{
cankao[i]=1;/*1表示放入*/
value1+=array[i];/*背包剩余容量减少*/
}
else
cankao[i]=0;
if(value1==value)
return 1;
return 0;
}
void main()
{
long array[N];
int cankao[N]={0};
int cankao1[N]={0};
int i;
long value,value1=0;
clrscr();
create(array,N,K);
output(array,N);
printf("\nInput the value of beibao:\n");
scanf("%ld",&value);
beibao(array,cankao,value,N);
for(i=0;i<N;i++)
if(cankao[i]==1)
value1+=array[i];
if(value==value1)
{
printf("\nWe have got a solution,that is:\n");
for(i=0;i<N;i++)
if(cankao[i]==1)
{
if(i%5==0)
printf("\n");
printf("%13ld",array[i]);
}
}
else
printf("\nSorry.We have not got a solution.\n");
printf("\nSecond method:\n");
if(beibao1(array,cankao1,value,N)==1)
{
for(i=0;i<N;i++)
if(cankao1[i]==1)
{
if(i%5==0)
printf("\n");
printf("%13ld",array[i]);
}
}
else
printf("\nSorry.We have not got a solution.\n");
}
4)动态规划算法
解决0/1背包问题的方法有多种,最常用的有贪婪法和动态规划法。其中贪婪法无法得到问题的最优解,而动态规划法都可以得到最优解,下面是用动态规划法来解决0/1背包问题。
动态规划算法与分治法类似,其基本思想是将待求解问题分解成若干个子问题,然后从这些子问题的解得到原问题的解。与分治法不同的是,适合于用动态规划法求解的问题,经分解得到的子问题往往不是互相独立的,若用分治法解这类问题,则分解得到的子问题数目太多,以至于最后解决原问题需要耗费过多的时间。动态规划法又和贪婪算法有些一样,在动态规划中,可将一个问题的解决方案视为一系列决策的结果。不同的是,在贪婪算法中,每采用一次贪婪准则便做出一个不可撤回的决策,而在动态规划中,还要考察每个最优决策序列中是否包含一个最优子序列。
0/1背包问题
在0 / 1背包问题中,需对容量为c 的背包进行装载。从n 个物品中选取装入背包的物品,每件物品i 的重量为wi ,价值为pi 。对于可行的背包装载,背包中物品的总重量不能超过背包的容量,最佳装载是指所装入的物品价值最高,即p1*x1+p2*x1+...+pi*xi(其1<=i<=n,x取0或1,取1表示选取物品i) 取得最大值。
在该问题中需要决定x1 .. xn的值。假设按i = 1,2,...,n 的次序来确定xi 的值。如果置x1 = 0,则问题转变为相对于其余物品(即物品2,3,.,n),背包容量仍为c 的背包问题。若置x1 = 1,问题就变为关于最大背包容量为c-w1 的问题。现设r?{c,c-w1 } 为剩余的背包容量。
在第一次决策之后,剩下的问题便是考虑背包容量为r 时的决策。不管x1 是0或是1,[x2 ,.,xn ] 必须是第一次决策之后的一个最优方案,如果不是,则会有一个更好的方案[y2,.,yn ],因而[x1,y2,.,yn ]是一个更好的方案。
假设n=3, w=[100,14,10], p=[20,18,15], c= 116。若设x1 = 1,则在本次决策之后,可用的背包容量为r= 116-100=16 。[x2,x3 ]=[0,1] 符合容量限制的条件,所得值为1 5,但因为[x2,x3 ]= [1,0] 同样符合容量条件且所得值为1 8,因此[x2,x3 ] = [ 0,1] 并非最优策略。即x= [ 1,0,1] 可改进为x= [ 1,1,0 ]。若设x1 = 0,则对于剩下的两种物品而言,容量限制条件为116。总之,如果子问题的结果[x2,x3 ]不是剩余情况下的一个最优解,则[x1,x2,x3 ]也不会是总体的最优解。在此问题中,最优决策序列由最优决策子序列组成。假设f (i,y) 表示剩余容量为y,剩余物品为i,i + 1,...,n 时的最优解的值,即:利用最优序列由最优子序列构成的结论,可得到f 的递归式为:
当j>=wi时: f(i,j)=max{f(i+1,j),f(i+1,j-wi)+vi} ①式
当0<=j<wi时:f(i,j)=f(i+1,j) ②式
fn( 1 ,c) 是初始时背包问题的最优解。
以本题为例:若0≤y<1 0,则f ( 3 ,y) = 0;若y≥1 0,f ( 3 ,y) = 1 5。利用②式,可得f (2, y) = 0 ( 0≤y<10 );f(2,y)= 1 5(1 0≤y<1 4);f(2,y)= 1 8(1 4≤y<2 4)和f(2,y)= 3 3(y≥2 4)。因此最优解f ( 1 , 11 6 ) = m a x {f(2,11 6),f(2,11 6 - w1)+ p1} = m a x {f(2,11 6),f(2,1 6)+ 2 0 } = m a x { 3 3,3 8 } = 3 8。
现在计算xi 值,步骤如下:若f ( 1 ,c) =f ( 2 ,c),则x1 = 0,否则x1 = 1。接下来需从剩余容量c-w1中寻求最优解,用f (2, c-w1) 表示最优解。依此类推,可得到所有的xi (i= 1.n) 值。
在该例中,可得出f ( 2 , 116 ) = 3 3≠f ( 1 , 11 6 ),所以x1 = 1。接着利用返回值3 8 -p1=18 计算x2 及x3,此时r = 11 6 -w1 = 1 6,又由f ( 2 , 1 6 ) = 1 8,得f ( 3 , 1 6 ) = 1 4≠f ( 2 , 1 6 ),因此x2 = 1,此时r= 1 6 -w2 = 2,所以f (3,2) =0,即得x3 = 0。
请问8D问题求解法的步骤是什么?
8D问题求解法是汽车行业普遍使用的处理问题的一种系统化方法,它提供了一套符合逻辑的解决问题的方法。,但在实际应用中却有9个步骤:D0:征兆紧急反应措施;D1:小组成立;D2:问题说明;D3:实施并验证临时措施;D4:确定并验证根本原因;D5:选择和验证永久纠正措施;D6:实施永久纠正措施;D7:...
初中数学课程标准认知性学习目标水平的分类与表述
具体内容设计应考虑到学生的年龄特征与知识背景,分别选取数学人物介绍、数学故事、数学应用介绍、数学问题求解等形式。如:第三学段应当向学生介绍数学在人类发展过程和当代科技领域中的重要作用,让学生在数学活动中体会证明的必要性并学会证明,从理性上认识有关数学结论的正确性。 (4)形成实事求是的态度以及进行质疑和...
计算思维是人类求解问题的一条途径
计算思维是人类求解问题的一条途径是对的。1、计算思维概述 计算思维是一种解决问题的思考方式,它运用计算机科学的基础概念和技术,将复杂的问题转化为可解决的小问题,从而找到问题的解决方案。计算思维不仅在计算机领域有着广泛的应用,在其他领域中也同样适用。计算思维可以帮助人们更好地理解和解决现实...
订购移动流量包为什么不扣钱。问题简单求解
流量包扣费可以是立即收取或月内补收,当前未扣费也会在计费更新后补收。1、办理的是赠送流量包、活动流量包,则本身属于免费的,不会扣费;2、属于有扣费的流量包,按照不同流量包的规则,收费时间也不一样。目前大部分流量包是以生效后立即收费规则,但也有少部分流量包是月末补收(如保底类流量...
问题:物理题求解- -。 描述:飞机在2km的高空以360km\/h的速度沿 水平航 ...
包裹相对地面做平抛运动,初速度v0与飞机的速度相同。落地时间,利用竖直方向自由落体来求得:h=½gt²t=√2h\/g=20s 包裹落地处离地面观察员的距离就是相对地面的水平位移,利用水平匀速直线运动来求:x=v0t=360×20\/3600=2km 包裹水平速度与飞机相同,离飞机的水平距离为0....
四皇后问题求解
如果应用回溯法求解问题的所有解,要回溯到解空间树的树根,这样根结点的所有子树都被 探索 到才结束。如果只要求解问题的一个解,问题的最终解,因此要跳过对以该结点为根的子树的系统 探索 ,逐层向其祖先结点回溯。这个过程叫做解空间树的那么在 探索 解空间树时,只要搜索到问题的一个解就可以...
管综考研的分值分别是多少?
管综分数构成如下:1、管综的试卷结构包括选择题和主观题两个部分。其中,选择题包括数学、逻辑推理和写作三个部分,而主观题则主要涉及案例分析和写作。2、数学部分:总分为75分,包括问题求解、条件充分性判断和逻辑推理三类题目。其中,问题求解共15题,每题3分,共45分;条件充分性判断共10题,每题3...
win10 安装.AppxBundle程序问题,求解,用powershell 指向出现如下?_百度...
您好,对于你的遇到的问题,我很高兴能为你提供帮助,我之前也遇到过哟,以下是我的个人看法,希望能帮助到你,若有错误,还望见谅!| 加个参数试一下呢:1 Get-AppxPackage -AllUsers |专 ForEach-Object { Add-AppxPackage -DisableDevelopmentMode -ForceApplicationShutdown -Register "<string>"}...
今天我的包皮上出现红斑,类似内出血,无突出 ,是怎么回事呀?求解
问题分析:您好,包皮上长红斑,有几种可能性:如果是“实心”红点点,有可能是冠状沟发炎所致的包皮龟头炎;如果类似于上火的小泡泡,看起来晶莹剔透,有可能是疱疹病毒;类似于菜花样、瘊子样,有可能是尖锐湿疣。不同的病情,治疗的方法也是不同的。意见建议:建议您及时的到正规的医院去检查,针对治疗...
pnp问题的求解方法有
PNP问题(Point Non-Point Problem)是指在水资源管理中,对点源和非点源污染进行定量评估和管理的问题。为了解决PNP问题,可以采用以下方法:1. 监测和数据收集:首先,需要对水体中的点源和非点源污染进行监测和数据收集。这包括收集点源排放数据、非点源污染物入渗和径流数据,以及水体中的水质监测...
程昆盆炎: 3.2 背包问题 背包问题有三种 1.部分背包问题 一个旅行者有一个最多能用m公斤的背包,现在有n种物品,它们的总重量分别是W1,W2,...,Wn,它们的总价值分别为C1,C2,...,Cn.求旅行者能获得最大总价值. 解决问题的方法是贪心算法:将C1/W...
黄平县18619152235: C语言动态规划之背包问题求解 - ?
程昆盆炎: #include<stdio.h> int max(int a,int b) { if (a>b) return a; else return b; } int main() { //int max(int , int ); int n,m,i,j; int data[101][2]; int f[101][101]; scanf("%d%d",&n,&m); //n表示个数,m表示能背的最大重量 for(i=1;i<=n;i++) { scanf("%d%d",&data[...
黄平县18619152235: 动态规划的01背包问题,求解释. - ?
程昆盆炎: 注意到原来每次f[i][v]只用了一次,所以现在f[v]相当于原来的f[v], 上次循环保存的f[v]相当于原来的f[i-1][v] 如果从0做到V的话,没有重复限制,会从v->v+c[i]->v+2*c[i]加上去,本次循环的c[i]也会加上
黄平县18619152235: 算法分析与设计题目 请求解0/1/2背包问题:有1个背包、其容量为C,有n种物品(每个物品种类i都自己的重量wi和价值vi),找出一个最优装包方案,使得包... - ?
程昆盆炎:[答案] (1) m(i,j)=max( m(i-1,j-w[i])+v[i] , m(i-1,j) , m(i-1,j-2*w[i])+2*v[i] );(2) for (int i=0;i<=n;i++) for (int j=0;j<=c;j++) m[i][j]=-...
黄平县18619152235: 求背包问题详解?
程昆盆炎: 是编程里的背包问题么 这里有dd大神的 背包九讲的一部分 LZ先凑合看下吧 P01: 01背包问题 题目 有N件物品和一个容量为V的背包.第i件物品的费用是c[i],价值是w[i].求解将哪些物品装入背包可使价值总和最大. 基本思路 这是最基础的背包...
黄平县18619152235: 求助一道c++背包问题 需要用递归的方法解决已知背包可放入的质量为S,现有n件物品,质量分别为w1,w2,w3...wn,能否从这n件物品中选择若干件放入此... - ?
程昆盆炎:[答案] 1.排序,删掉大于S的物品.2.编码,放入为1,不放入为0.一个编码100111…就是一种物品的选择.3.从00000开始到11111,遍历一遍就OK了.想用递归的话1.排序,从小到大2.从0000开始,如果总质量小于S,2进制序列加1,作为变量传送...
黄平县18619152235: 背包问题算法?
程昆盆炎: 首先建立一个堆栈,里面存放的是物品信息.算法开始后,按照一定的次序存放物品,每放进去一个物品,就检查是否越界,如果没越界,就继续选择物品放入(入栈);如果越界,就退出当前物品(出栈),当正好装满一个背包时,记录当前栈到一个数组,并退出顶端物品(出栈),往后放物品……一直到栈空为止,这样可以找到所有最佳存放方法.
黄平县18619152235: 用动态规划算法怎样求解01背包问题 - ?
程昆盆炎: 动态规划主要解决的是多阶段的决策问题.01背包中,状态为背包剩余的容量,阶段是每一个物品,决策是是否选择当前的物品.所以用动态规划来解决是非常贴切的.我们设f[V]表示已经使用容量为V时所能获得的最大价值,w[i]表示i物品的质...
黄平县18619152235: ...价值是w[i].求解将哪些物品装入背包可使价值总和最大.---------------------------------------------------------------------------------------------------------基本思路这是最基础的... - ?
程昆盆炎:[答案] 注意到原来每次f[i][v]只用了一次,所以现在f[v]相当于原来的f[v], 上次循环保存的f[v]相当于原来的f[i-1][v] 如果从0做到V的话,没有重复限制,会从v->v+c[i]->v+2*c[i]加上去,本次循环的c[i]也会加上
黄平县18619152235: 背包问题的问法变化 - ?
程昆盆炎: 以上涉及的各种背包问题都是要求在背包容量(费用)的限制下求可以取到的最大价值,但背包问题还有很多种灵活的问法,在这里值得提一下.但是我认为,只要深入理解了求背包问题最大价值的方法,即使问法变化了,也是不难想出算法的...