一个类似价格和重量的背包问题,望高手帮解答一下

liuhao0226 2009-09-03 07:28:56
已知正整数p1,p2,...,pn, W1,W2,...,Wn和M,寻找 W1*X1+W2*X2+...+Wn*Xn <= M 条件下,
X1,X2,。。。,Xn,0<=Xi<=1,使得 p1*X1+p2*X2+。。。+Pn*Xn最大化。

我已经明白,怎么可以使 p1*W1+p2*W2+。。。+Pn*Wn 最大化,可是不明白怎么使上面的问题最大化

有没有哪个高手帮我解释一下,先谢谢了。。。
...全文
135 15 打赏 收藏 转发到动态 举报
写回复
用AI写文章
15 条回复
切换为时间正序
请发表友善的回复…
发表回复
linren 2009-09-04
  • 打赏
  • 举报
回复
【测试用例1】
#define MY_N 5
#define MY_M 50
int p[MY_N]={10,20,15,46,7};
int w[MY_N]={45,32,78,47,23};

【测试结果1】
z=98    x[5]=1, x[1]=1, x[3]=1, x[2]=1, x[4]=1,         is not answer...

z=91 x[1]=1, x[3]=1, x[2]=1, x[4]=1, is not answer...

z=88 x[5]=1, x[3]=1, x[2]=1, x[4]=1, is not answer...

z=81 x[3]=1, x[2]=1, x[4]=1, is not answer...

z=83 x[5]=1, x[1]=1, x[2]=1, x[4]=1, is not answer...

z=76 x[1]=1, x[2]=1, x[4]=1, is not answer...

z=73 x[5]=1, x[2]=1, x[4]=1, is not answer...

z=66 x[2]=1, x[4]=1, is not answer...

z=78 x[5]=1, x[1]=1, x[3]=1, x[4]=1, is not answer...

z=71 x[1]=1, x[3]=1, x[4]=1, is not answer...

z=68 x[5]=1, x[3]=1, x[4]=1, is not answer...

z=61 x[3]=1, x[4]=1, is not answer...

z=63 x[5]=1, x[1]=1, x[4]=1, is not answer...

z=56 x[1]=1, x[4]=1, is not answer...

z=53 x[5]=1, x[4]=1, is not answer...

z=46 x[4]=1, is answer!

Press any key to continue

【说明1】
限重50……
没有办法选择多个……
只能选则一个……
w[]中红色的是可以选择的……
int p[MY_N]={10,20,15,46,7};
int w[MY_N]={45,32,78,47,23};
p[]中蓝色的就是最优的结果……



【测试用例2】
#define MY_N 5
#define MY_M 10
int p[MY_N]={10,20,15,46,7};
int w[MY_N]={45,32,78,47,23};

【测试结果2】
z=98    x[5]=1, x[1]=1, x[3]=1, x[2]=1, x[4]=1,         is not answer...

z=91 x[1]=1, x[3]=1, x[2]=1, x[4]=1, is not answer...

z=88 x[5]=1, x[3]=1, x[2]=1, x[4]=1, is not answer...

z=81 x[3]=1, x[2]=1, x[4]=1, is not answer...

z=83 x[5]=1, x[1]=1, x[2]=1, x[4]=1, is not answer...

z=76 x[1]=1, x[2]=1, x[4]=1, is not answer...

z=73 x[5]=1, x[2]=1, x[4]=1, is not answer...

z=66 x[2]=1, x[4]=1, is not answer...

z=78 x[5]=1, x[1]=1, x[3]=1, x[4]=1, is not answer...

z=71 x[1]=1, x[3]=1, x[4]=1, is not answer...

z=68 x[5]=1, x[3]=1, x[4]=1, is not answer...

z=61 x[3]=1, x[4]=1, is not answer...

z=63 x[5]=1, x[1]=1, x[4]=1, is not answer...

z=56 x[1]=1, x[4]=1, is not answer...

z=53 x[5]=1, x[4]=1, is not answer...

z=46 x[4]=1, is not answer...

z=52 x[5]=1, x[1]=1, x[3]=1, x[2]=1, is not answer...

z=45 x[1]=1, x[3]=1, x[2]=1, is not answer...

z=42 x[5]=1, x[3]=1, x[2]=1, is not answer...

z=35 x[3]=1, x[2]=1, is not answer...

z=37 x[5]=1, x[1]=1, x[2]=1, is not answer...

z=30 x[1]=1, x[2]=1, is not answer...

z=27 x[5]=1, x[2]=1, is not answer...

z=20 x[2]=1, is not answer...

z=32 x[5]=1, x[1]=1, x[3]=1, is not answer...

z=25 x[1]=1, x[3]=1, is not answer...

z=22 x[5]=1, x[3]=1, is not answer...

z=15 x[3]=1, is not answer...

z=17 x[5]=1, x[1]=1, is not answer...

z=10 x[1]=1, is not answer...

z=7 x[5]=1, is not answer...

z=0 not find answer!
Press any key to continue

【说明2】
因为限重为10……
而所有的物品都大于10……
所以最后什么都没有选择……
chuengchuenghq 2009-09-04
  • 打赏
  • 举报
回复
up
linren 2009-09-04
  • 打赏
  • 举报
回复
(上接11楼)

11楼的程序有些问题……
对循环的判定有错误……

下面是正确的程序了:

【程序】
#include <stdio.h>
#include <stdlib.h>
#include <string.h>

/**只用修改这里*********************/
#define MY_N 5
#define MY_M 200
int p[MY_N]={10,20,15,46,7};
int w[MY_N]={45,32,78,47,23};
/*********************只用修改这里**/

struct node{
int i;
int p;
};

int compar(const void *a,const void *b){
struct node *aa,*bb;
aa=(struct node*)a;
bb=(struct node*)b;
if(aa->p>bb->p) return 1;
if(aa->p==bb->p) return 0;
return -1;
}

void fun(int *p,int *w,int n,int m){
struct node *ls;
char *xk;
int i,j;
int z,sum_p,sum_w,a,b,c,d;
ls=(struct node*)malloc(sizeof(struct node)*n);
xk=(char*)malloc(sizeof(char)*n);

sum_p=0;sum_w=0;
for(i=0;i<n;i++){
ls[i].i=i;
ls[i].p=p[i];
sum_p+=p[i];
sum_w+=w[i];
}
a=m-sum_w;
qsort(ls,n,sizeof(struct node),compar);

for(j=0;;j++){
memset(xk,0,sizeof(char)*n);
d=0;
for(i=0;i<n;i++){
if(j&(1<<i)){
xk[i]=1;d++;
}
}
b=0;c=0;
for(i=0;i<n;i++){
b+=w[ls[i].i]*xk[i];
c+=p[ls[i].i]*xk[i];
}
z=sum_p-c;
printf("z=%d\t",z);
for(i=0;i<n;i++){
if(xk[i]==0) printf("x[%d]=1, ",ls[i].i+1);
}
if(d==n){
printf("\tnot find answer!\n");break;
}
if(-b<=a){
printf("\tis answer!\n\n");break;
}else{
printf("\tis not answer...\n\n");
}
}

free(ls);free(xk);
}

int main(){
fun(p,w,MY_N,MY_M);
return 0;
}
linren 2009-09-04
  • 打赏
  • 举报
回复
【程序】
#include <stdio.h>
#include <stdlib.h>
#include <string.h>

/**只用修改这里*********************/
#define MY_N 5
#define MY_M 200
int p[MY_N]={10,20,15,46,7};
int w[MY_N]={45,32,78,47,23};
/*********************只用修改这里**/

struct node{
int i;
int p;
};

int compar(const void *a,const void *b){
struct node *aa,*bb;
aa=(struct node*)a;
bb=(struct node*)b;
if(aa->p>bb->p) return 1;
if(aa->p==bb->p) return 0;
return -1;
}

void fun(int *p,int *w,int n,int m){
struct node *ls;
char *xk;
int i,j;
int z,sum_p,sum_w,a,b,c;
ls=(struct node*)malloc(sizeof(struct node)*n);
xk=(char*)malloc(sizeof(char)*n);

sum_p=0;sum_w=0;
for(i=0;i<n;i++){
ls[i].i=i;
ls[i].p=p[i];
sum_p+=p[i];
sum_w+=w[i];
}
a=m-sum_w;
qsort(ls,n,sizeof(struct node),compar);

for(j=0;j<=n;j++){
memset(xk,0,sizeof(char)*n);
for(i=0;i<n;i++){
if(j&(1<<i)) xk[i]=1;
}
b=0;c=0;
for(i=0;i<n;i++){
b+=w[ls[i].i]*xk[i];
c+=p[ls[i].i]*xk[i];
}
z=sum_p-c;
printf("z=%d\t",z);
for(i=0;i<n;i++){
if(xk[i]==0) printf("x[%d]=1, ",ls[i].i+1);
}
if(-b<=a){
printf("\tis answer!\n\n");
break;
}else{
printf("\tis not answer...\n\n");
}
}

free(ls);free(xk);
}

int main(){
fun(p,w,MY_N,MY_M);
return 0;
}

【运行结果】
z=98    x[5]=1, x[1]=1, x[3]=1, x[2]=1, x[4]=1,         is not answer...

z=91 x[1]=1, x[3]=1, x[2]=1, x[4]=1, is not answer...

z=88 x[5]=1, x[3]=1, x[2]=1, x[4]=1, is answer!

Press any key to continue

【说明】
以上是对6楼+8楼算法的一个实现……
丈八涯 2009-09-04
  • 打赏
  • 举报
回复
是01背包问题,只是价值有一个计算公式罢了。

http://blog.csdn.net/g_idea/archive/2009/08/24/4477020.aspx
  • 打赏
  • 举报
回复
这个问题准确的说,是叫MIP 混合整数规划,或者叫混合整数线性规划问题。
如果不是特别的原因非得自己实现,
建议楼主也可以去网上找相关的lp_sover (线性规划)库。

单纯形法可以实现,而且效果也不错。


[Quote=引用 2 楼 litaoye 的回复:]
确实是线性规划问题,LZ可以看看单纯型法!
[/Quote]
linren2 2009-09-03
  • 打赏
  • 举报
回复
[Quote=引用 7 楼 peacefulby 的回复:]

同学,Xi不一定是0和1啊……
不过你那个累加符号是怎么打出来的我很好奇:)
[/Quote]
是使用了特殊的软件盘^_^……
linren2 2009-09-03
  • 打赏
  • 举报
回复
[Quote=引用 6 楼 linren 的回复:]
建立一个表
把Xi'按照|pi|的大小从小到大排序
得到顺序:Xk1,Xk2,...,Xkn

按照二进制递增枚举:
Xk1,Xk2,...,Xkn
00 ...0
100
...
[/Quote]
这段话有误……
应该是:

建立一个表
把Xi'按照|pi|的大小从小到大排序
得到顺序:Xk1',Xk2',...,Xkn'

按照二进制递增枚举:
Xk1',Xk2',Xk3',...,Xkn'
0 0 0 ... 0
1 0 0 ... 0
1 1 0 ... 0
...


当遇到第一个满足条件①的情况时
即为最优解……

6楼中忘记给“Xki”加“'”了……
PeacefulBY 2009-09-03
  • 打赏
  • 举报
回复
[Quote=引用 6 楼 linren 的回复:]
Assembly codeMax Z = p1*X1+p2*X2+...+Pn*Xn
= ∑(pi*Xi)

W1*X1+W2*X2+...+Wn*Xn
= ∑(Wi*Xi) <= M

设:
1-Xi'=Xi

则:
Assembly codeMax Z = ∑[pi*(1-Xi')]
Max Z = (∑pi) - (∑(pi*Xi'))

∑[Wi*(1-Xi')] <= M
-∑(Wi*Xi') <= M-∑Wi ①

建立一个表
把Xi'按照|pi|的大小从小到大排序
得到顺序:Xk1,Xk2,...,Xkn

按照二进制递增枚举:
Assembly codeXk1,Xk2,...,Xkn00 ...0100
...

当遇到第一个满足条件①的情况时
即为最优解……
[/Quote]
同学,Xi不一定是0和1啊……
不过你那个累加符号是怎么打出来的我很好奇:)
linren 2009-09-03
  • 打赏
  • 举报
回复
Max Z = p1*X1+p2*X2+...+Pn*Xn 
= ∑(pi*Xi)

W1*X1+W2*X2+...+Wn*Xn
= ∑(Wi*Xi) <= M


设:
1-Xi'=Xi

则:
Max Z = ∑[pi*(1-Xi')]
Max Z = (∑pi) - (∑(pi*Xi'))

∑[Wi*(1-Xi')] <= M
-∑(Wi*Xi') <= M-∑Wi ①


建立一个表
把Xi'按照|pi|的大小从小到大排序
得到顺序:Xk1,Xk2,...,Xkn

按照二进制递增枚举:
Xk1,Xk2,...,Xkn
0 0 ... 0
1 0 0
...


当遇到第一个满足条件①的情况时
即为最优解……
linren 2009-09-03
  • 打赏
  • 举报
回复
linren 2009-09-03
  • 打赏
  • 举报
回复
应该是0-1规划……
可以用隐枚举法来求解……
showjim 2009-09-03
  • 打赏
  • 举报
回复
先用贪婪法取p/W序列,限定最小和MW与Mp,同时缓存中间结果序列pW[]。
然后穷举组合MW<=x<=M,动态更新Mp,根据pW[]可中断不合条件的分枝.
绿色夹克衫 2009-09-03
  • 打赏
  • 举报
回复
确实是线性规划问题,LZ可以看看单纯型法!
PeacefulBY 2009-09-03
  • 打赏
  • 举报
回复
线性规划问题,类似于二维坐标系,然后类推到高维

33,028

社区成员

发帖
与我相关
我的任务
社区描述
数据结构与算法相关内容讨论专区
社区管理员
  • 数据结构与算法社区
加入社区
  • 近7日
  • 近30日
  • 至今
社区公告
暂无公告

试试用AI创作助手写篇文章吧