if((i+1)%20==0)
cout<}
cout<m=weight(0,n-1);
if(m==-1)
cout<<"没有伪造硬币"<else
cout<<"伪造硬币的位置是"<cout<return0;
}
//称重函数m,n分别为数组的最小及最大下标,每次把硬币等分三堆
intweight(intm,intn){
intj=0;
inti=0;
intsum1=0;
intsum2=0;
intsum3=0;
if(m>=n)
return-1;
for(i=0;i<(n-m+1)/3;i++,j++)
{
sum1+=(a[m+j]);
sum2+=(a[m+(n-m+1)/3+j]);
sum3+=(a[m+2*(n-m+1)/3+j]);
}
//数组元素个数除三余一的情况
if(((n-m+1)%3)==1)
{
if(sum1==sum2)
{
if(sum1==sum3)
{
if(a[n]==a[n-1])
return-1;
else
returnn;
}
else
{
m=m+2*((n-m+1)/3);
weight(m,n);
}
}
else
if(sum1==sum3)
{
m=m+(n-m+1)/3;
n=m+2*((n-m+1)/3)-1;
weight(m,n);
}
else
{
n=m+(n-m+1)/3-1;
weight(m,n);
}
}
//数组元素个数除三余二的情况
else
if(((n-m+1)%3)==2)
{
if(sum1==sum2)
{
if(sum1==sum3)
{
if(a[n]==a[n-2])
{
if(a[n-1]==a[n-2])
return-1;
else
returnn-1;
}
else
returnn;
}
else
{
m=m+2*((n-m+1)/3);
weight(m,n);
}
}
else
if(sum1==sum3)
{
m=m+(n-m+1)/3;
n=m+2*((n-m+1)/3)-1;
weight(m,n);
}
else
{
n=m+(n-m+1)/3-1;
weight(m,n);
}
}
//数组元素个数被三整除的情况
else
if(sum1==sum2)
{
if(sum1==sum3)
{
return-1;
}
else
{
m=m+2*((n-m+1)/3);
weight(m,n);
}
}
else
{
if(sum1==sum3)
{
m=m+(n-m+1)/3;
n=m+2*((n-m+1)/3)-1;
weight(m,n);
}
else
{
n=m+(n-m+1)/3-1;
weight(m,n);
}
}
}
实验结果
2.找零钱问题
源程序如下:
#include
intmain()
{
intmoney,value,returns;
inttwenty_five,ten,five,one;
inti,j,k,l;
i=0;
j=0;
k=0;
l=0;
money=100;
value=33;
returns=money-value;
cout<<"***应该找给孩子的钱是(美分):
"<cout<<"***请输入现有的25美分,10美分,5美分,1美分硬币的个数***"<cin>>twenty_five>>ten>>five>>one;
i=returns/25;
if(i<=twenty_five)
returns-=25*i;
else
{
returns-=twenty_five*25;
i=twenty_five;
}
if(returns>0)
{
j=returns/10;
if(j<=ten)
returns-=10*j;
else
{
returns-=ten*10;
j=ten;
}
}
if(returns>0)
{
k=returns/5;
if(k<=five)
returns-=5*k;
else
{
returns-=five*5;
k=five;
}
}
if(returns>0)
{
l=returns;
if(l<=one)
returns-=l;
else
{
returns-=one;
l=one;
}
}
if((returns=returns-(i*25+j*10+k*5+l))>0)
cout<<"不好意思,现在没有足够的硬币!
"<else
{
cout<<"***应找25美分的个数是:
"<
cout<<"***应找10美分的个数是:
"<cout<<"***应找5美分的个数是:
"<cout<<"***应找1美分的个数是:
"<}
return0;
}
实验结果:
实验二:
一、实验目的与要求
熟悉C/C++语言的集成开发环境;
通过本实验加深对贪心算法、动态规划和回溯算法的理解。
二、实验内容:
掌握贪心算法、动态规划和回溯算法的概念和基本思想,分析并掌握"0-1"背包问题的三种算法,并分析其优缺点。
三、实验题
1."0-1"背包问题的贪心算法
2."0-1"背包问题的动态规划算法
3."0-1"背包问题的回溯算法
四.1
"0-1"背包问题的贪心算法源程序:
#include
#include
usingnamespacestd;
structgood//表示物品的结构体
{
doublep;//价值
doublew;//重量
doubler;//价值与重量的比
}a[200];
doubles,value,m,result;
inti,n;
boolbigger(gooda,goodb)
{
returna.r>b.r;
}
intmain()
{
printf("----------背包问题之贪心算法------------------\n");
printf("输入物品个数:
");
scanf("%d",&n);//物品个数
printf("输入物品的重量和价值:
");
for(i=0;i{
scanf("%lf%lf",&a[i].w,&a[i].p);
a[i].r=a[i].p/a[i].w;
}
sort(a,a+n,bigger);//调用sort排序函数,你大概不介意吧,按照价值与重量比排序贪心
printf("输入背包的容量;");
scanf("%lf",&m);//读入包的容量m
s=0;//包内现存货品的重量
value=0;//包内现存货品总价值
result=0;
for(i=0;i{value+=a[i].p;
s+=a[i].w;}
result=value*s;
printf("背包内物品总价值为:
%.2lf.\n",result);//输出结果
return0;
}
运行结果:
2
"0-1"背包问题的动态规划算法源程序
#include
#include
#include
#include
usingnamespacestd;
voidKnapsack(vectorvct_v,vectorvct_w,intc,intn);
voidprint(vectorv);
voidprintarr(vector>m,intp,intq);
voidTraceback(vector>m,vectorvct_w,intc,intn);
voidmain()
{
intmo=10;
vectorvct_w;
vectorvct_v;
intc,n,v,w;
cout<<"***0-1背包问题之动态规划***"<cout<<"***请输入物品个数***"<cin>>n;
srand((unsigned)time(NULL));
vct_w.push_back(n);//第一个位置存放物品个数
for(inti=1;i<=n;i++)
{
w=rand()%mo+1;
vct_w.push_back(w);
}
vct_v.push_back(n);
for(i=1;i<=n;i++)
{
v=rand()%mo+10;
vct_v.push_back(v);
}
cout<<"***请输入背包容量***"<cin>>c;
cout<<"***请输入物品重量***"<print(vct_w);
cout<<"***请输入物品价值***"<print(vct_v);
Knapsack(vct_v,vct_w,c,n);
}
voidprint(vectorv)
{
for(inti=1;i{
cout<}
cout<}
voidprintarr(vector>m,intp,intq)
{
for(inti=1;i<=p;i++)
{
for(intj=1;j<=q;j++)
{
cout<}
cout<}
cout<}
voidKnapsack(vectorvct_v,vectorvct_w,intc,intn)
{
vector>m(n+1,vector(c+1));
intjMax;
for(inti=0;i<=n;i++)//为每一行分配空间
jMax=vct_w[n]-1vct_w[n]-1:
c;
for(intj=0;j<=jMax;j++)
m[n][j]=0;
for(j=vct_w[n];j<=c;j++)
m[n][j]=vct_v[n];
for(i=n-1;i>1;i--)
{
intjMax=vct_w[i]-1vct_w[i]-1:
c;
for(intj=0;j<=jMax;j++)
m[i][j]=m[i+1][j];
for(j=vct_w[i];j<=c;j++)
m[i][j]=m[i+1][j]>m[i+1][j-vct_w[i]]+vct_v[i]?
m[i+1][j]:
m[i+1][j-vct_w[i]]+vct_v[i];
}
m[1][c]=m[2][c];
if(c>=vct_w[1])
m[1][c]=m[1][c]>m[2][c-vct_w[1]]+vct_v[1]?
m[1][c]:
m[2][c-vct_w[1]]+vct_v[1];
cout<<"***m列表内容***"<printarr(m,n,c);
Traceback(m,vct_w,c,n);
}
voidTraceback(vector>m,vectorvct_w,intc,intn)
{
vectorx;
x.push_back(0);
for(inti=1;i{
if(m[i][c]==m[i+1][c])
x.push_back(0);
else
{x.push_back
(1);
c-=vct_w[i];
}
}
x.push_back((m[n][c])>0?
1:
0);
cout<<"***动态规划所得的最优解为***"<for(i=1;i{
cout<}
cout<}
运行结果:
3
"0-1"背包问题的回溯算法源程序
#include
#include
#include
intmin(intw,intc)
{inttemp;
if(welse
temp=c;
returntemp;
}
intmax(intw,intc)
{
inttemp;
if(w>c)temp=w;
else
temp=c;
returntemp;
}
voidknapsack(intv[],intw[],intc,intn,int**m)//求最优值
{
intjmax=min(w[n]-1,c);
for(intj=0;j<=jmax;j++)
m[n][j]=0;
for(intjj=w[n];jj<=c;jj++)
m[n][jj]=v[n];
for(inti=n-1;i>1;i--){//递归部分
jmax=min(w[i]-1,c);
for(intj=0;j<=jmax;j++)
m[i][j]=m[i+1][j];
for(intjj=w[i];jj<=c;jj++)
m[i][jj]=max(m[i+1][jj],m[i+1][jj-w[i]]+v[i]);
}
m[1][c]=m[2][c];
if(c>=w[1])
m[1][c]=max(m[1][c],m[2][c-w[1]]+v[1]);
cout<<"最优值:
"<for(intl=2;l<=n;l++)
for(intj=0;j<=c;j++)
{
cout<}
cout<cout<<"*******************************************"<}
inttraceback(int**m,intw[],intc,intn,intx[])//回代,求最优解
{
cout<<"得到的一组最优解如下:
"<for(inti=1;iif(m[i][c]==m[i+1][c])x[i]=0;
else{x[i]=1;
c-=w[i];}
x[n]=(m[n][c])?
1:
0;
for(inty=1;y<=n;y++)
{
cout<}
returnx[n];
}
main()
{
intn,c;
int**m;
cout<<"------------------0-1背包问题之回溯--------------------"<cout<<"请输入物品个数和重量上限:
";
cin>>n>>c;
int*v=newint[n+1];
cout<<"输入各物品价值(v[i]):
"<for(inti=1;i<=n;i++)
cin>>v[i];
int*w=newint[n+1];
cout<<"输入各物品重量(w[i]):
"<for(intj=1;j<=n;j++)
cin>>w[j];
int*x=newint[n+1];
m=newint*[n+1];//动态的分配二维数组
for(intp=0;p{
m[p]=newint[c+1];
}
knapsack(v,w,c,n,m);
traceback(m,w,c,n,x);
}
运行结果:
部分: