算法设计与分析例题

来源:互联网 发布:阿里云 快照 编辑:程序博客网 时间:2024/06/06 05:55

//模仿人工的大整数加法

int add(int m,int a[],int n,int b[],int c[])

{ int i,k,p,q;

    if(m>n){k=m;for(i=n;i<k;i++) b[i]=0;}

   else{k=n;for(i=m;i<k;i++) a[i]=0;}

       p=0;

for(i=0;i<k;i++){q=a[i]+b[i]+p;c[i]=q%10;p=q/10;}

    if(p){c[k]=p;k=k+1;}

return(k);

}

//采用分治策略的大整数乘法。

int mult(int n,int a[],int b[],int c[])

int i,q,n1,n2,k,k1,k2,k3,m1,m2;

int a1[50],a2[50],b1[50],b2[50],c1[50],c2[50],pp[200],qq[200],rr[200];

if(n==1) {

q=a[0]*b[0];c[0]=q%10;c[1]=q/10;return(2*n);

}

n1=(int)(0.5*(float)(n+1));n2=(int)(0.5*(float)n);

printf("n1=%d,n2=%d\n",n1,n2);

for(i=0;i<n2;i++) {a2[i]=a[i]; b2[i]=b[i];}

for(i=0;i<n1;i++) {a1[i]=a[n2+i];b1[i]=b[n2+i];} 

    

        for(i=n1-1;i>=0;i--) printf("%d",a1[i]);printf("a1\n\n");

for(i=n2-1;i>=0;i--) printf("%d",a2[i]);printf("a2\n\n");

        for(i=n1-1;i>=0;i--) printf("%d",b1[i]);printf("b1\n\n");

for(i=n2-1;i>=0;i--) printf("%d",b2[i]);printf("b2\n\n");

k1=mult(n1,a1,b1,qq);

k2=mult(n2,a2,b2,rr);

for(i=k1-1;i>=0;i--) printf("%d",qq[i]);printf("qq\n\n");

for(i=k2-1;i>=0;i--) printf("%d",rr[i]);printf("rr\n\n");

   

m1=add(n1,a1,n1,a2,c1);

m2=add(n2,b1,n2,b2,c2);

k3=mult(n1,c1,c2,pp);

for(i=m1-1;i>=0;i--) printf("-%d",c1[i]);printf("c1\n\n");

for(i=m2-1;i>=0;i--) printf("*%d",c2[i]);printf("c2\n\n");

for(i=k3-1;i>=0;i--) printf("%d",pp[i]);printf("pp\n\n");

m1=sub(k3,pp,k1,qq,c1);

m2=sub(m1,c1,k2,rr,c2);

        for(i=m1-1;i>=0;i--) printf("---%d",c1[i]);printf("c1\n\n");

for(i=m2-1;i>=0;i--) printf("***%d",c2[i]);printf("c2\n\n");

for(i=n-1;i>=0;i--) {qq[i+n]=qq[i];qq[i]=0;}

for(i=m2-1;i>=0;i--) {c2[i+n1]=c2[i];c2[i]=0;}

    

k1=add(2*n,qq,m2+n1,c2,c1);   

k2=add(k1,c1,k2,rr,c);for(i=2*n-1;i>=0;i--) printf("%d",c[i]);printf("c  \n\n");

for(i=2*n-1;i>=0;i--) printf("%d",qq[i]);printf("--qq\n\n");

for(i=m2+n1-1;i>=0;i--) printf("%d",c2[i]);printf("--c2\n\n");

for(i=k1-1;i>=0;i--) printf("%d",c1[i]);printf("++c1  \n\n");

for(i=k2-1;i>=0;i--) printf("%d",c[i]);printf("==c  \n\n");

    return(2*n);

}

void main(int argc,char argv[])//采用分治策略的大整数乘法主程序

{

    int i,m,n,k;

int a[100]={4,2,3,1,3,4,5,6,7};

int b[100]={1,2,3,4,4,7,8,6,1,9,1,1,8,9,7,6};

int c[100]={0};n=4;

for(i=n-1;i>=0;i--) printf("%d",a[i]);printf("\n\n");

        for(i=n-1;i>=0;i--) printf("%d",b[i]);printf("\n\n");

k=mult(n,a,b,c);

printf("\n=======k=%d\n",k);    

for(i=k-1;i>=0;i--) printf("%d",c[i]);printf("\n\n");

 }

void main(int argc,char argv[])   //模仿人工的大整数加减法主程序

{

    int i,m,n,k;

int a[100]={4,5,1,3,3,4,5,6,7};

int b[100]={3,2,1,2,4,7,8,6,1,9,1,1,8,9,7,6};

int c[100]={0};

m=4;n=4;

k=sub(m,a,4,b,c);

printf("\nk=%d\n",k);

    for(i=m-1;i>=0;i--) printf("%d",a[i]);printf("\n\n");

    for(i=n-1;i>=0;i--) printf("%d",b[i]);printf("\n\n");

for(i=k-1;i>=0;i--) printf("%d",c[i]);printf("\n\n");

 }

//52页例1,分别用递归和循环来做 #include "stdio.h"

float f1(int n)  //递归计算1*3*5*......*(2n-1),(2n-1)!

{ if(n= =1)return 1.0;

return((2*n-1)*(2.0*n-2)*f1(n-1));

}

float f2(int n)  //递归求解52页例1

{   int sign=-1;

if(n==1)return 1.0;

if(n%2) sign=1;

return(sign/f1(n)+f2(n-1));

}

int main()  //52页例1,其中打印了前6项每次的求和结果。

{   int i,n,j,sign=1;

float x,s,t;

    for(x=1.0;x<7.0;x=x+1.0)printf("%5.2f,%15.6f,%15.6f\n",x,f1(x),f2(x));

printf("\n"); //以上是递归方法,以下是循环方法,结果可对照看出。

t=1.0;s=1.0;n=6;

for(i=2;i<=n;i++){

  t=1;for(j=1;j<=2*i-1;j++)t=t*j;

  sign=-sign;s=s+sign/t;

  printf("n=%d,t=%15.2f,  1.0/t=%8.6f,  s=%8.6f\n",n,t,1.0/t,s);

  }

}

//寻找完全数,利用定义,使用循环。

int main()

{ int i,j,k,s,a[60];

for(i=2;i<9000;i++){ //29000逐一检查。

s=1;k=0; //第一个因子1不再求,直接列入和s中。

for(j=2;j<=i/2;j++) if(i%j ==0){s=s+j;a[k++]=j;} //2i/2寻找因子。

if(s==i){printf("s=%d,its factor are\n",s);

         for(j=0;j<k;j++) printf(",a[%d]=%d ",j,a[j]);printf("\n");}

}

return 0;}

//寻找完全数,用递归方法求小于自己的所有不同因子。

#include "stdio.h"

int a[15];

int f(int m,int k)  //递归寻找m的第k个因子,调用时从f(m,1)开始,结果存数组a[k]

{ int i;

i=a[k-1]+1;  //从前一个因子加1开始寻找新的因子。

while((m%i !=0) && 2*i<m ) i++;

if(2*i>m) return k; //再没有因子了。

a[k]=i; //找到一个因子。

f(m,k+1); //递归去寻找下一个因子。

}

int main()

{ int i,m,t,s;

    a[0]=1; //第一个因子永远是1

for(m=6;m<9000;m++){  //可从2开始逐个数字寻找。

  t=f(m,1);s=0; //t是找到因子个数,至少一个1,可能多个。

      for(i=0;i<t;i++) s=s+a[i]; //求因子的和,等于自身就是完全数。

  if(s == m) for(i=0;i<t;i++)printf("\nt=%d,m=%d,a[%d]=%d",t,m,i,a[i]);

}

return 0;

}

//寻找完全数时用递归方法求小于自己的所有不同因子的改进。

void g(int n,int m,int *k,int a[])       //检查m是否为n的因子。

{ if(!(n%m)) a[(*k)++]=m;  //mn因子时存放于数组a下标(*k)处,下标自增1

    if(n<2*m) return; else g(n,m+1,k,a);   //m>n/2时找完结束,否则递归检查m+1

}

int main()

{int i,k,n,s,a[100];a[0]=1;

for(n=2;n<9000;n++){ 

k=1;g(n,2,&k,a); //递归求因子,进入时k=1,结束时k是因子个数。

s=0;for(i=0;i<k;i++) s=s+a[i];//求各因子的和。

if(s==n) {printf("n=%d\n",n);for(i=0;i<k;i++) printf("a[%d]=%d,s=%d\n",i,a[i],s);}

}}

//十进制正整数从低到高位输出,高到低位输出,推广到任意进制转换。吕国英书61页例7

#include <stdio.h>

#include <math.h>

void f1(int n)   //反序输出各位数字,即低到高位

{if(n<10)printf("%d ",n);else {printf("%d ",n%10);f1(n/10);}}

void f2(int n) //正序输出各位数字,即高到低位

{if(n<10)printf("%d ",n);else {f2(n/10);printf("%d ",n%10);}}

void f3(int n,int m)   //十进制数n转换为m进制数。

{if(n<m)printf("%d ",n);else {f3(n/m,m);printf("%d ",n%m);}}

void main()

{int n;int m=10;

int j,i=0,a[20];

n=12345;do printf("%d ",n%10); while(n=n/10);

printf("\n");n=12345;f1(n);

printf("\n");n=12345;while(n>10){a[i++]=n%10;n=n/10;}a[i]=n;

for(j=i;j>=0;j--) printf("%d ",a[j]);

printf("\n");n=12345;f2(n);

printf("\n八进制");n=12345;f3(n,8);

printf("\n十六进制");n=12345;f3(n,16);

printf("\n");getchar();

}

//任意正整数表示为2的方幂,吕国英书63页例89

#include <stdio.h>

void ttrryy(int n,int r)         //要将n表示为2的方幂,n减半到1结束, 

{if(n==1) printf("2(%d)",r);    //r表示递归进行次数,从0向上升。

else {ttrryy(n/2,r+1);if(n%2 == 1)printf("+2(%d)",r);}}

void t2(int n, int r) //前的修改,使指数部分也表示为2的方幂

{ if(n==1){ switch(r)

    { case 0:printf("2(0)");break;

     case 1:printf("2");break;

             case 2:printf("2(2)");break;

     default:printf("2(");t2(r,0);printf(")");

    }}else 

{t2(n/2,r+1);

   if(n%2 == 1) switch(r)

  {case 0:printf("+2(0)");break;

           case 1:printf("+2");break;

                   case 2:printf("+2(2)");break;

               default:printf("+2(");t2(r,0);printf(")");

  }}

}

void main()

{ int n;

for(n=2;n<20;n++) if(n>=1) {printf("%d = ",n);ttrryy(n,0);printf("\n");}else printf("error");

getchar();t2(137,0); getchar();

}

//递归计算组合数,吕国英书65页例10

#include <stdio.h>

int a[100];

void comb(int m,int k)

{ int i,j;printf("[%d,%d]",m,k); //为看清递归过程加入的显示

for(i=m;i>=k;i--){

a[k]=i;if(k>1) comb(i-1,k-1);else for(j=a[0];j>0;j--) printf("%d ",a[j]);printf("\n");

}}

void main()

{int n,r;n=5;r=3;a[0]=r;comb(n,r);getchar();}

//x,使x2是各位数字不同的九位数。吕国英书76页例16

void main()

{ int x,y1,y2;

  int p[10],i,t,k,num=0;

  for(x=10000;x<32000;x++){

  for(i=0;i<10;i++) p[i]=1;

  y1=x*x;

  y2=y1;k=0;

  for(i=1;i<=9;i++){ 

  t=y2%10;y2=y2/10;  //if(t==0)break;可找必出现数字1—9的共30组,

  if(p[t]==1) {p[t]=0;k++;}else break;  //如(1118262 =139854276……

  }

  if(k==9){num++;printf("num=%3d, x=%6d, x*x=%10d\n",num,x,y1);}

}}  //共找到83组,(110124*10124=102495376……

//大整数乘法,吕国英书147页例16

void main()

{ int b,c,d,i,i1,i2,j,k,n,n1,n2,a[256];

char s1[256],s2[256];

strcpy(s1,"12345678910");strcpy(s2,"26");

for(i=0;i<256;i++)a[i]=0;

n1=strlen(s1);n2=strlen(s2);d=0;

for(i1=0,k=n1-1;i1<n1;i1++,k--){

for(i2=0,j=n2-1;i2<n2;i2++,j--){

i=i1+i2;b=a[i]+(s1[k]-48)*(s2[j]-48)+d;

a[i]=b%10;d=b/10;}

while(d>0){i++;a[i]=a[i]+d%10;d=d/10;}

n=i;}

for(i=n;i>=0;i--)printf("%d ",a[i]);

}

//大整数乘法,字符串s1记一个大整数,乘另一个不超过C语言整数范围的整数c

#include <stdio.h>   //吕国英书78页例18

#include <string.h>

void main()

{ int b,c,d,i,j,n;

  int a[256];

  char s1[256];

  strcpy(s1,"12345678910");

  c=5;          //要作乘法 s1*c

  n=strlen(s1);

  d=0;          //d记进位,初为0

  for(i=0,j=n-1;i<n;i++,j--){

  b=(s1[j]-48)*c+d; //一位相乘,c是一位数时b最多是2位数

  a[i]=b%10;         //a[i]得本位

  d=b/10;            //d得下次进位,因对c,不限制是1位数,d也可能多位

  }

  while(d != 0) a[n++]=d%10; //d位数较多时

  for(i=n-1;i>=0;i--)printf("%d",a[i]);//乘积数组每个元素只记一位数,存储有浪费。

}

//计算n!, n为较大整数,100-550左右,吕国英书79页例19

#include <stdio.h>

#include <math.h>

void main()

{ int b,d,i,j,m,n,r;

  int a[256];

  n=100;        //要计算100!

  m=(int)(log(n)/log(10.0)*n/6.0)+2;//loge为底

  a[0]=1;        //80页不同数组从0起使用

  for(i=1;i<m;i++) a[i]=0;  

  d=0;          //d记进位,初为0

  for(i=2;i<=100;i++){

  for(j=0;j<m;j++){

  b=a[j]*i+d;   //""相乘,b最多是2""

  a[j]=b%1000000;//a[i]得本位

//printf("--i=%d,j=%d,b=%d,%d  ",i,j,b,a[j]);

  d=b/1000000;}//d得下次进位

  if(d!=0) a[j]=d;

  }

  for(i=m-1;i>=0;i--){if(a[i]==0) continue;else {r=i;break;}}

  printf("%5d!=%6d ",n,a[r]);j=1;//j调整行,使输出同80页一致

  for(i=r-1;i>=0;i--){

  j++;if(!(j%6))printf("\n");

      if(a[i]>99999) {printf("%d ",a[i]);continue;}

  if(a[i]>9999) {printf("0%d ",a[i]);continue;}

  if(a[i]>999) {printf("00%d ",a[i]);continue;}

  if(a[i]>99) {printf("000%d ",a[i]);continue;}

  if(a[i]>9) {printf("0000%d ",a[i]);continue;}

  printf("00000%d ",a[i]);

  }

}

//填写运算符,使n[0]等于 n[1],n[2],n[3],n[4],n[5]用运算符连接求得的值,

void main()                                  //吕国英书101页例34

{ int j,k,f,i[5],total; double n[6],p,q;

  char c[5]={' ','+','-','*','/'}; //0位置是一个空格

  n[0]=9.9;n[1]=2; n[2]=5;n[3]=9; n[4]=3;n[5]=6; total=0;//本例9.9=2/5+9+3/6

  for(i[1]=1;i[1]<=4;i[1]++)  //i[1]=1,2,3,4对应+-*/其余同

  if(i[1]<4 || n[2]!=0)    //避免0除,以下同

  for(i[2]=1;i[2]<=4;i[2]++)

  if(i[2]<4 || n[3]!=0)

                    for(i[3]=1;i[3]<=4;i[3]++)

                   if(i[3]<4 || n[4]!=0)

                 for(i[4]=1;i[4]<=4;i[4]++)

 if(i[4]<4 || n[5]!=0){

 p=0;q=n[1];f=1;

 for(k=1;k<=4;k++)

 switch(i[k]){  //注意乘除先做的实现

 case 1:p=p+f*q;f=1;q=n[k+1];break;

 case 2:p=p+f*q;f=-1;q=n[k+1];break;

 case 3:q=q*n[k+1];break;

 case 4:q=q/n[k+1];

 }

 if(p+f*q==n[0]){total++;printf("total=%d  ",total);

     for(k=1;k<=4;k++) printf("%5.1f%c",n[k],c[i[k]]);

 printf("%5.1f=%5.1f\n",n[5],n[0]);}

 }

 if(total==0)printf("No solution");

}

//n箱产品中找次品,次品比正品每件轻10克,依次取1,2,4,8,16……计算与标准的差

void main()   //吕国英书102页例35  

{ int i,k,n,t,w1,w2;

n=3;t=1;w1=0;w2=620;

for(i=1;i<=n;i++){printf("box=%d,units=%d ",i,t);w1=w1+t;t*=2;}

w1*=100;printf("%5d ",w1); 

w1=(w1-w2)/10;  //w1应该的标准重,w2称重,减后两重的差仍放w1

while(w1){k=0;t=1; //w1计算那几个箱子是次品

while(w1-t>=0){t*=2;k++;}

printf("%d box is bad",k);

w1=w1-t/2;}

}

//输入n,计算第n行的杨辉三角形系数,吕国英书108页例37

void coeff(int a[],int n)

{int i;if (n==1)a[1]=a[2]=1;

else {coeff(a,n-1); a[n+1]=1; for(i=n;i>=2;i--) a[i]+=a[i-1];a[1]=1;}

}

void main()

{ int b[100],i,n,k;

n=6;coeff(b,n);  //递归版本

for(i=1;i<=n+1;i++)printf("%d ",b[i]);

b[1]=b[2]=1;k=1;//不用递归,循环中完成各次计算

while(k<=n){printf("\n");

  for(i=1;i<=k;i++)printf("%d ",b[i]);

  b[k+1]=1; for(i=k;i>=2;i--) b[i]+=b[i-1];k++;}

}

//n个数据,循环移动k位,吕国英书109页例38

int gcd(int a,int b)//求最大公因

{int i,t=1;

for(i=2;i<=a && i<=b;i++)while( !(a%i) && !(b%i)){t=t*i;a=a/i;b=b/i;}

return(t);}

void main()

{ int a[100],b[100],b0,b1,i,n,k,j,t,tt,m;

n=16;k=4;

for(i=0;i<n;i++)printf("%d ",a[i]=i);//原数组

printf("\n");

for(i=0;i<n;i++)b[(k+i)%n]=a[i];   //解法1,送入另一数组b

for(i=0;i<n;i++) printf("%d ",b[i]);

printf("\n");

for(i=0;i<k;i++){                  //解法2,每次移动一位,移动k

t=a[n-1];for(j=n-1;j>0;j--) a[j]=a[j-1]; a[0]=t;}

for(i=0;i<n;i++)printf("%d ",a[i]);

printf("\n\n");   //解法3,移动m次,每次n/m个数

m=gcd(n,k);

for(j=0;j<m;j++){b0=a[j];tt=j;for(i=0;i<n/m;i++){tt=(tt+k)%n;b1=a[tt];a[tt]=b0;b0=b1;}}

for(i=0;i<n;i++)for(i=0;i<n;i++)printf("%d ",a[i]);

}

//穿越沙漠问题,吕国英书128页例5

void main()

{ int dis,k,oil;

  dis=500;k=1;oil=500;

  do{

  printf("storepoint(%d),distance(%d),oilquantity(%d)\n",k,1000-dis,oil);

  k++;dis+=500/(2*k-1);oil=500*k;}while(dis<1000);

  oil=500*k+(1000-dis)*(2*k-1);

  printf("--storepoint(%d),distance(%d),oilquantity(%d)\n",k,1000-dis,oil);

}

//残缺棋盘问题,2k*2k棋盘用2*2残缺一格棋盘覆盖,吕国英书143页例14

int amount=0,Board[100][100];// amount块覆盖,预设大小100*100, 实用大小由k指定

void cover(int tr,int tc,int dr,int dc,int size) //行列号0—2k-1

{int s,t;             // printf("(%d,%d,%d,%d,%d)",tr,tc,dr,dc,size);

 if(size<2)return;

 amount++; t=amount;s=size/2;

 if(dr<tr+s && dc<tc+s){ cover(tr,tc,dr,dc,s);  Board[tr+s-1][tc+s]=Board[tr+s][tc+s-1]=Board[tr+s][tc+s]=t;//printf("(1)s=%d\n",s);output(8);

 cover(tr,tc+s,tr+s-1,tc+s,s);cover(tr+s,tc,tr+s,tc+s-1,s);cover(tr+s,tc+s,tr+s,tc+s,s);}

 else if (dr<tr+s && dc>=tc+s){ cover(tr,tc+s,dr,dc,s);  Board[tr+s-1][tc+s-1]=Board[tr+s][tc+s-1]=Board[tr+s][tc+s]=t;//printf("(2)s=%d\n",s);output(8);

 cover(tr,tc,tr+s-1,tc+s-1,s);cover(tr+s,tc,tr+s,tc+s-1,s);cover(tr+s,tc+s,tr+s,tc+s,s);}

 else if(dr>=tr+s && dc<tc+s){ cover(tr+s,tc,dr,dc,s);  Board[tr+s-1][tc+s-1]=Board[tr+s-1][tc+s]=Board[tr+s][tc+s]=t;//printf("(3)s=%d\n",s);output(8);

 cover(tr,tc,tr+s-1,tc+s-1,s);cover(tr,tc+s,tr+s-1,tc+s,s);cover(tr+s,tc+s,tr+s,tc+s,s);}

 else if(dr>=tr+s && dc>=tc+s){cover(tr+s,tc+s,dr,dc,s);  Board[tr+s-1][tc+s-1]=Board[tr+s-1][tc+s]=Board[tr+s][tc+s-1]=t;

//printf("(4)s=%d\n",s);output(8);

 cover(tr,tc,tr+s-1,tc+s-1,s);cover(tr,tc+s,tr+s-1,tc+s,s);cover(tr+s,tc,tr+s,tc+s-1,s);}

}

void output(int size) //输出到文件以便存放在下面。

{ int i,j;

FILE *fp;fp=fopen("w1.txt","w");

for(i=0;i<size;i++){for(j=0;j<size;j++) fprintf(fp,"%2d ",Board[i][j]);fprintf(fp,"\n");}

fclose(fp);}

void main()

{ int size=1,x,y,i,j,k;

k=3; for(i=1;i<=k;i++)size*=2;

x=1;y=0; cover(0,0,x,y,size); output(size);

}

//输出的情况

3  3  4 4   9  9  10 10 

0  3  2 4   9  7  7  10 

5  2  2 6   8  8  7  11 

5  5  6 6   1  8  11 11 

14 14 13 1   1  18  19 19 

14 12 13 13  18  18 17 19 

15 12 12 16  20  17 17 21 

15 15 16 16  20  20 21 21

//最大子段和,吕国英书146页例15265页节6.4  

int maxsubsum(int a[],int left,int right)

{ int center,i,j,sum,lsum,rsum,s1,s2,ls,rs;

if(left==right) if(a[left]>0) return(a[left]);else return(0);

   else {center=(left+right)/2;//printf("left=%d,right=%d,center=%d\n ",left,right,center);

   lsum=maxsubsum(a,left,center);rsum=maxsubsum(a,center+1,right);

   s1=0;ls=0;for(i=center;i>=left;i--){ls+=a[i];if(ls>s1)s1=ls;}

       s2=0;rs=0;for(i=center+1;i<=right;i++){rs+=a[i];if(rs>s2)s2=rs;}

  // printf("(lsum=%d,rsum=%d,ls=%d,rs=%d,s1=%d,s2=%d)\n",lsum,rsum,ls,rs,s1,s2);

   if(s1+s2<lsum && rsum<lsum)return(ls);

   if(s1+s2<rsum) return(rs);

   return(s1+s2);

}}

void main()

{ int b[]={-2,11,-4,13,-5,-2};int x;

x=maxsubsum(b,0,5);printf("x=%d ",x);}

//递归计算第二小的吕国英书151页例17

#include <stdio.h>

#include <stdlib.h>

float a[100];

void two(int i,int j,float *fm2,float *fm1)//从第i到第j,按 fm2>fm1 输出,fm22

{ float lm1,lm2,rm1,rm2;

int mid; printf("---i=%d j=%d ",i,j);

if(i==j) *fm2=*fm1=a[i]; //i==j是一个元素,输出,i == j-1是二个,输出按大小

else if(i == j-1) if(a[i]<a[j]){*fm2=a[j];*fm1=a[i];} else {*fm2=a[i];*fm1=a[j];}

     else {mid=(i+j)/2; //左右分求

 two(i,mid,&lm2,&lm1);printf("(1)lm2=%5.2f lm1=%5.2f\n",lm2,lm1);

      two(mid+1,j,&rm2,&rm1);printf("(2)rm2=%5.2f rm1=%5.2f\n",rm2,rm1); 

 if (lm1<rm1)   //以下是四个数取出第2小的

              if(lm2<rm1){*fm1=lm1;*fm2=lm2;}else{*fm1=lm1;*fm2=rm1;} 

  else if(rm2<lm1){*fm1=rm1;*fm2=rm2;} else {*fm1=rm1;*fm2=lm1;}

}}

float second(int n)

{ float m1,m2; two(0,n-1,&m2,&m1);//printf("(3)m2=%5.2f m1=%5.2f\n",m2,m1);

 return(m2);}

void main()

{   int i,n;float min2;

n=100;for(i=0;i<n;i++)a[i]=rand()/100.0;

n=4;for(i=n-1;i>=0;i--)printf("%5.2f   ",a[i]);

min2=second(n);printf("min2=%5.2f\n",min2);

}

//递归计算第k吕国英书152页例18

void swap(int *x,int *y){int t;t=*x;*x=*y;*y=t;} //交换两个变量的值

int select(int a[],int left,int right,int k)

{int i,j,pivot;//printf("---left=%d,right=%d\n",left,right);

 if(left>=right) return(a[left]);

 pivot=a[left];i=left+1;j=right;//printf("\ni=%d,j=%d,pivot=%d\n",i,j,pivot);

 while(1){

 while (a[i]<pivot)i++;//printf("\ni=%d ",i);

 while (a[j]>pivot)j--;// printf("\nj=%d ",j);

 if(i>=j) break;

 swap(&a[i],&a[j]);

 }

 if(j-left+1 == k) return(pivot);

 a[left]=a[j];a[j]=pivot;

 if(j-left+1 < k) return(select(a,j+1,right,k-j-1+left));else return(select(a,left,j-1,k));

}

int xzwt(int a[],int n,int k)

{if(k<1 || k>n){printf("\nerror");return(-1);}

return(select(a,0,n-1,k));}

void main()

{  int num[]={2,3,1,8,6,4,10,24,33,44,22};

   int i,m; for(i=0;i<11;i++) printf("%d ",num[i]);

   for(i=0;i<=12;i++) {m=xzwt(num,11,i); printf("\nm=%d",m);}

}

//正整数n去掉s个数字,使从左至右按原次序剩下整数最小。吕国英154页例19

#include <stdio.h>

#include <string.h>

void del(char n[],int b,int k){int i;  //printf("**%s ",n);从j位开始删掉k

for(i=b;i<=strlen(n)-k;i++)n[i]=n[i+k];}

void main()

{  char n[100];int s,i,j,j1,c,len,data[100]; //字符方式给出整数n0位不用,如“01000083”

   strcpy(n,"0120083");s=3;len=strlen(n); //012345678,012435863,0231183,0120083,012345833

   printf("len=%d \n",len);if(s>len){printf("error");return;}

   j1=0;

   for(i=1;i<=s;i++){

   for(j=1;j<strlen(n)-1;j++){

   if(n[j]>n[j+1]){printf("--i=%d,j=%d,%s ",i,j,n);//前比后大,前删,后覆盖前移

                   del(n,j,1);printf("^^i=%d,j=%d,%s \n",i,j,n);

//   data[i]=j; //若位置按删后重算,j就是删除位置。

               if(j>=j1)data[i]=j+i-1;else data[i]=data[i-1]-1; //记录删除原位置

j1=j; break;}} //本次循环只删1个数字,下次从头再来

    if(j>= strlen(n))break; //如上循环没有发生删除,到此跳出。

   }

   printf("##i=%d,%s ",i,n);

   for(i=i;i<=s;i++){j=len-i;del(n,j,1);data[i]=j;}

   while(n[1]=='0' && strlen(n)>2) del(n,1,1);printf("[%s] ",n);

   for(i=1;i<=s;i++) printf(",%d ",data[i]);printf("---、\n\n"); //以下是解法2

   strcpy(n,"0120083");s=3;len=strlen(n); i=1;j=1;j1=0;

   while(i<=s && j<=strlen(n)-1){

   while(n[j]<=n[j+1]) j++; printf("j=%d ",j);

   if(j<strlen(n)){printf("--i=%d,j=%d,%s ",i,j,n);

   del(n,j,1);printf("^^i=%d,j=%d,%s \n",i,j,n);

   if(j>=j1)data[i]=j+i-1;else data[i]=data[i-1]-1;

   i++;j1=j;j--;}}

   while(n[1]=='0' && strlen(n)>2) del(n,1,1);printf("[%s] ",n);

   for(i=1;i<=s;i++) printf(",%d ",data[i]);

}

//数塔的动态规划算法吕国英书168页例24

void main()

{  int a[50][50][3],i,j,n=5;

   a[1][1][1]=9;

   a[2][1][1]=12;a[2][2][1]=15;

   a[3][1][1]=10;a[3][2][1]=6;a[3][3][1]=8;

   a[4][1][1]=2;a[4][2][1]=18;a[4][3][1]=9;a[4][4][1]=5;

   a[5][1][1]=19;a[5][2][1]=7;a[5][3][1]=10;a[5][4][1]=4;a[5][5][1]=16; //已知的数塔

   for(i=1;i<=n;i++)for(j=1;j<=i;j++){a[i][j][2]=a[i][j][1];a[i][j][3]=0;}

   for(i=n-1;i>=1;i--)

   for(j=1;j<=i;j++)

if(a[i+1][j][2]>a[i+1][j+1][2]) //实现动态规划各阶段的计算。   {printf("i=%d,j=%d,%d>%d\n",i,j,a[i+1][j][2],a[i+1][j+1][2]);a[i][j][2]+=a[i+1][j][2];}

   else {a[i][j][2]+=a[i+1][j+1][2];a[i][j][3]=1;}

   printf("max=%d\n",a[1][1][2]);j=1;

   for(i=1;i<=n-1;i++){printf("%d-->",a[i][j][1]);j+=a[i][j][3];} printf("%d\n",a[n][j][1]);

 }

//循环赛日程表(4种)吕国英书251页节6.1

#include <stdio.h>

int a[50][50];

void out(int a[][50],int m)  //显示a数组的m*m部分

{int i,j;for(i=1;i<=m;i++){printf("\n");for(j=1;j<=m;j++)printf("%3d",a[i][j]);}}

void dimidiate(int i,int j,int n)  //递归填写

{ int k1,k2;

if(n==2){a[i][n]=j;a[j][n]=i;a[i][n-1]=i;a[j][n-1]=j;}  //2*2直接填写

else {dimidiate(i,i+n/2-1,n/2);dimidiate(i+n/2,j,n/2); // 左上、左下

for(k1=n;k1>n/2;k1--){

for(k2=i;k2<=i-1+n/2;k2++) a[k2][k1]=a[k2+n/2][k1-n/2]; //右上

    for(k2=i+n/2;k2<=i-1+n;k2++) a[k2][k1]=a[k2-n/2][k1-n/2];}}}  //右下

void main()

{  int i,j,k,n=1;int n0,m,k1,k2;int s,t;int k0;

   k=4;for(i=1;i<=k;i++) n=n*2;

   dimidiate(1,n,n); out(a,n);

   printf("(2)\n");m=n;for(i=1;i<=n;i++)for(j=1;j<=n;j++)a[i][j]=0;//解法2先取消上次结果   

   for(i=1;i<=n;i++)a[i][1]=i;out(a,n);//第一列数据填入

   for(n=2;n<=m;n=n*2){n0=n/2;   //n=2,4,8...,对列,按规则送数

                        for(k1=n;k1>n0;k1--)

for(i=1;i<m;i+=n){

for(k2=i;k2<=i-1+n0;k2++)a[k2][k1]=a[k2+n0][k1-n0];

                                for(k2=i+n0;k2<=i-1+n;k2++)a[k2][k1]=a[k2-n0][k1-n0];}}

   n=n/2;out(a,n);

   printf("(3)\n");for(i=1;i<=n;i++)for(j=1;j<=n;j++)a[i][j]=0;//解法3先取消上次结果

    m=1;n0=n;for(j=1;j<=n;j++)a[1][j]=j;out(a,n);//第一行数据填入

    for(s=1;s<=k;s++){                                 //n=2,4,8...,对行,按规则送数

   n0=n0/2;for(t=1;t<=n0;t++)

   for(i=m+1;i<=2*m;i++)

   for(j=m+1;j<=2*m;j++){

   a[i][j+(t-1)*m*2]=a[i-m][j+(t-1)*m*2-m];

   a[i][j+(t-1)*m*2-m]=a[i-m][j+(t-1)*m*2];}

   m=m*2;}

   out(a,n);

   printf("(4)\n");for(i=1;i<=n;i++)for(j=1;j<=n;j++)a[i][j]=0;//解法4先取消上次结果

   a[1][1]=1;n0=1;n=2;//二维递推,从 a[1][1]=1开始

   for(k0=1;k0<=k;k0++){

   for(i=n0+1;i<=n;i++)for(j=1;j<=n;j++) a[i][j]=a[i-n0][j]+n0;

       for(j=n0+1;j<=n;j++)for(i=1;i<=n0;i++) a[i][j]=a[i][j-n0]+n0;

       for(j=n0+1;j<=n;j++)for(i=n0+1;i<=n;i++) a[i][j]=a[i][j-n0]-n0;

   n0=n;n=n*2;}

   n=n/2;out(a,n);

}

//最大子段和问题,5个解答吕国英书146页例15265页节6.4

#include <stdio.h>

int maxsum1(int a[],int n,int *besti,int *bestj)

{ int i,j,k,tsum,sum=0;*besti=*bestj=0;

for(i=1;i<=n;i++)

for(j=1;j<=n;j++){

tsum=0;for(k=i;k<=j;k++) tsum+=a[k];

if(tsum>sum){sum=tsum;*besti=i;*bestj=j;}}

return(sum);

}

int maxsum2(int a[],int n,int *besti,int *bestj)

{int i,j,tsum,sum=0;*besti=*bestj=0;

for(i=1;i<=n;i++){tsum=0;

for(j=i;j<=n;j++) {tsum+=a[j];if(tsum>sum){sum=tsum;*besti=i;*bestj=j;}}

}return(sum);}

int maxsum3(int a[],int left,int right)

{ int center,i,lsum,rsum,s1,s2,les,ris;

    if(left == right) if(a[left]>0) return(a[left]);else return(0);

    else {center=(left+right)/2;

      lsum=maxsum3(a,left,center);

  rsum=maxsum3(a,center+1,right);

  s1=0;les=0;for(i=center;i>=left;i--){les+=a[i];if(les>s1)s1=les;}

          s2=0;ris=0;for(i=center+1;i<=right;i++){ris+=a[i];if(ris>s2)s2=ris;}

      if(s1+s2<lsum && rsum<lsum)return(lsum);

  if(s1+s2<ris) return(rsum);

  return(s1+s2);}}

int maxsum4(int a[],int n,int *besti,int *bestj)

{int i,j,tsum[50],sum[50];

for(i=0;i<=n;i++) tsum[i]=sum[i]=0;*besti=*bestj=0;i=1;

for(j=1;j<=n;j++){

    tsum[j]=tsum[j-1]+a[j];printf("(j=%d,%d--%d)",j,tsum[j],sum[j]);

if(tsum[j]>sum[j-1]){sum[j]=tsum[j];*besti=i;*bestj=j;printf("\n*%d,%d,%d\n",j,tsum[j],sum[j]);}

else {sum[j]=sum[j-1];if(tsum[j]<=0){i=j+1;tsum[j]=0;}}

   }

printf("*besti=%d,%d ",*besti,*bestj);

return(sum[*bestj]);}

int maxsum5(int a[],int n,int *besti,int *bestj)

{int i,j,tsum,sum;

for(i=0;i<=n;i++) tsum=sum=0;*besti=*bestj=0;i=1;

for(j=1;j<=n;j++){

    tsum=tsum+a[j];printf("(j=%d,%d--%d)",j,tsum,sum);

if(tsum>sum){sum=tsum;*besti=i;*bestj=j;printf("\n*%d,%d,%d\n",j,tsum,sum);}

else if(tsum<=0){i=j+1;tsum=0;}

   }

printf("*besti=%d,%d ",*besti,*bestj);

return(sum);}

void main() //5个解答,每个调用一次

{ int num[100]={0,-2,11,-4,13,-5,-2};int i,j,t,n=6;

t=maxsum1(num,n,&i,&j);printf("(1)i=%d,j=%d,maxsum=%d\n",i,j,t);

t=maxsum2(num,n,&i,&j);printf("(2)i=%d,j=%d,maxsum=%d\n",i,j,t);

t=maxsum3(num,1,n);printf("(3)maxsum=%d\n",t);

t=maxsum4(num,n,&i,&j);printf("(4)i=%d,j=%d,maxsum=%d\n",i,j,t);

t=maxsum5(num,n,&i,&j);printf("(5)i=%d,j=%d,maxsum=%d\n",i,j,t);}

//背包问题11种,给出6吕国英书270页节6.5

#include <stdio.h>

#include <math.h>

//double w[]={0,280,20,200,90,240,249,150,160,130};

//double max,total,p1[20],p[]={0,1,6,3,7,5,1,3,2,4};

double w[]={0,2,6};

double max,total,p1[20],p[]={0,3,4};

int x1[50],x[50];

void knap1()

{ int i,j,k,bi,bj,bk;

    double w,bestw=99999,a[10]={0,280,20,200,90,240,249,150,160,130};

for(i=1;i<=7;i++)

for(j=i+1;j<=8;j++)

for(k=j+1;k<=9;k++){  //printf("i=%d,j=%d,k=%d\n",i,j,k);

w=fabs(500-a[i]-a[j]-a[k]);

if(w<bestw){bestw=w;bi=i;bj=j;bk=k;}}

printf("(choose: %d,%d,%d,diff=%f,weight:%f)\n",bi,bj,bk,bestw,a[bi]+a[bj]+a[bk]);

}

void knap2()

{    double w,i1,i2,i3,i4,i5,i6,i10,i20,i30,i40,i50,i60,bestw=0.0;

for(i1=0;i1<=5;i1+=5)

   for(i2=0;i2<=2;i2+=2)

   for(i3=0;i3<=3.5;i3+=3.5)

          for(i4=0;i4<=1.7;i4+=1.7)

  for(i5=0;i5<=1;i5+=1)

  for(i6=0;i6<=5.1;i6+=5.1){

  w=i1+i2+i3+i4+i5+i6;

  if(w<=10.0 && w>=bestw){bestw=w;i10=i1;i20=i2;i30=i3;i40=i4;i50=i5;i60=i6;

  printf("(%5.2f,%5.2f,%5.2f,%5.2f,%5.2f,%5.2f)\n",i10,i20,i30,i40,i50,i60);}}

printf("(%5.2f,%5.2f,%5.2f,%5.2f,%5.2f,%5.2f)\n",i10,i20,i30,i40,i50,i60);

}

int knap3(double s,int n)

{

if(fabs(s)<1e-003) return(1);

else if(s<0.0 || (s>0 && n<1)) return(0);

else if(knap3(s-w[n],n-1)){printf("(choose:%d,%5.2f)\n",n,w[n]);return(1);}

else return(knap3(s,n-1));

}

void knap4()

{

int m,n,i,j,s,max,b[50];

double p1[50];

m=519;n=9;for(i=1,s=0;i<=n;i++){p1[i]=p[i];s=s+w[i];}

if(s<m) {printf("whole choose");return;}//for(j=1;j<=9;j++)printf("%5.3f ",p[j]/w[j]);

for(i=1;i<=n;i++){

max=1;for(j=2;j<=n;j++) if(p1[j]/w[j] > p1[max]/w[max]) max=j;

p1[max]=0;b[i]=max;}

for(i=1,s=0;s<m && i<=n;i++)s=s+w[b[i]];//应按b[]取到刚好不超过m停止,现超过1

if(s != m) w[b[i-1]]=m-(s-w[b[i-1]]);   //最后一种取m要减的,是s减最后超过那一件

for(j=1;j<=i-1;j++) printf("(choose:%d,weight:%5.2f)\n",b[j],w[b[j]]);

}

double knap5(int m,int i)          //背包装m,共i件,从第i件装, 

{   double max1,max2,t,s;int j;   //返回值是取得最大获利值即取得的p[]的总值

    max1=max2=s=t=0;

    for(j=1,s=0;j<=i;j++){s=s+w[j];t=t+p[j];}

    if(s<=m) {printf("whole choose");return(t);}

    if(i == 0) return(0);max1=knap5(m,i-1);

if(m>=w[i]) max2=knap5(m-w[i],i-1)+p[i];

if(max1>max2) t=max1;else t=max2;

printf(" (max1=%5.2f,max2=%5.2f) \n",max1,max2);

return(t);

}

void knap6(double m,int n,int i)//完善knap5m同上,n件数,从第i件开始

{   double t,s,sum=0;int j;s=t=0;

    for(j=1;j<=n;j++){s=s+w[j];t=t+p[j];}

    if(s<=m) {printf("(whole choose:%5.2f)\n",t);return;}

printf("m=%9.2f,n=%d,i=%i\n",m,n,i);

if(i==(n+1)){ //n件考虑完成

for(j=1;j<=n;j++) {sum=sum+x1[j]*p[j];

printf("j=%d,x1[j]=%d,sum=%9.2f,max=%9.2f\n",j,x1[j],sum,max);}

if(sum>max){max=sum;for(j=1;j<=n;j++)x[j]=x1[j];}

printf("(---i=%d,sum=%9.2f,max=%9.2f\n",i,sum,max);return;}

x1[i]=0;knap6(m,n,i+1);

if(total+w[i]<=m){printf("i=%d,total=%9.2f,",i,total);

x1[i]=1;total+=w[i];knap6(m,n,i+1);x1[i]=0;printf("**i=%d,total=%9.2f,",i,total);total-=w[i];}

return;

}

double bound(double m,int n,int k) //knap7使用的限界函数,对书上有修改,有调试时显示

{int i;double b,c,d;

printf("\nBound--max=%9.2f,m=%9.2f,n=%d,k=%d",max,m,n,k);

b=0;c=total;

for(i=1;i<k;i++) b=b+x[i]*p[i];

for(i=k+1;i<=n;i++){c=c+w[i];

printf("###b=%9.2f,c=%9.2f,max=%9.2f,total=%9.2f,i=%d",b,c,max,total,i);

if(c<m)b=b+p[i];else{ d=(b+(1-(c-m)/w[i])*p[i]);

printf("!!!b=%9.2f,c=%9.2f,max=%9.2f,total=%9.2f,d=%9.2f,i=%d",b,c,max,total,d,i);

return(d);}}

}

void sort(int n)  //排序,注意大的排在前面

{  double t,x[100];int i,j;

for(i=1;i<=n;i++) x[i]=p[i]/w[i];

for(i=n;i>1;i--) for(j=i-1;j>=1;j--) 

if(x[i]>x[j]){t=x[i];x[i]=x[j];x[j]=t;t=w[i];w[i]=w[j];w[j]=t;t=p[i];p[i]=p[j];p[j]=t;}

}

void knap7(double m,int n,int i)//完善knap6,加入限界,m同上,n件数,从第i件开始

{   double t,s,sum=0;int j;s=t=0;

    for(j=1;j<=n;j++){s=s+w[j];t=t+p[j];}

    if(s<=m) {printf("(whole choose:%5.2f)\n",t);return;}

printf("m=%9.2f,n=%d,i=%i\n",m,n,i);

if(i==(n+1)){ //n件考虑完成

for(j=1;j<=n;j++) {sum=sum+x1[j]*p[j];

printf("j=%d,x1[j]=%d,sum=%9.2f,max=%9.2f\n",j,x1[j],sum,max);

}

if(sum>max){max=sum;for(j=1;j<=n;j++)x[j]=x1[j];}

printf("(---i=%d,sum=%9.2f,max=%9.2f\n",i,sum,max);

return;}

if(total+w[i]<=m){printf("i=%d,total=%9.2f,",i,total);

x1[i]=1;total+=w[i];sum+=p[i];knap7(m,n,i+1);//printf("**i=%d,total=%9.2f,",i,total);

total-=w[i];sum-=p[i];x1[i]=0;}

if(i= =n || bound(m,n,i)>max  ){x1[i]=0;knap7(m,n,i+1); }

}

void knap8(double m,int n)  //非回溯的深度第一搜索

{int i,j;double sum=0;

 i=1;max=-1;

 while(1){while(i<=n && total+w[i]<=m){total+=w[i];sum+=p[i];x1[i]=1;i++;}

      printf("^^^i=%d,sum=%9.2f,max=%9.2f",i,sum,max);

          if(i==n+1 && max<sum){max=sum;i=n;for(j=1;j<=n;j++) x[j]=x1[j];} else x1[i]=0;

  while(bound(m,n,i)<=max){while(i>0 && x1[i] != 1) i--;

                            if(i==0)return;

x1[i]=0;total-=w[i];sum-=p[i];}

  i++;}}

struct {int i,flag,par;double cp,cw;} enode,node,q[1024];//knap9准备的结构体。

void knap9(double m,int n)  //宽度第一搜索,

{int j,f=0,e=0,beste=0,i=0;double bestp=0;

 enode.cw=enode.cp=0.0;enode.flag=enode.par=0;enode.i=0;q[e]=enode;

 while(e<498){

     node.cw=enode.cw+w[enode.i+1];

         printf("----f=%d,e=%d,enode.i=%d,enode.cw=%9.2f",f,e,enode.i,enode.cw);

 if(node.cw<=m){node.cp=enode.cp+p[enode.i+1];

                        if(node.cp>bestp){bestp=node.cp;beste=e+1;}

                node.flag=1;node.par=f;node.i=enode.i+1;e++;q[e]=node;

 printf("\n***q[%d].i=%d,bestp=%9.2f,beste=%d  ",e,q[e].i,bestp,beste);

 }

         node.cw=enode.cw;node.cp=enode.cp;node.flag=0;node.par=f;node.i=enode.i+1;

 e++;q[e]=node; f++;enode=q[f];

 printf("\nq[%d].i=%d,bestp=%9.2f,beste=%d  ",e,q[e].i,bestp,beste);

 }

 for(j=1;j<=n;j++){if(q[beste].flag==1)printf("choose %d",q[beste].i);beste=q[beste].par;}

 printf("\nMax=%9.2f)",bestp);}

int outnode(int n,int ee)   //模拟优先队优胜者出队,ee是队尾,从1查到ee

{int i,ff=-1;double w,mx=-1;//ff初值-1,若保持返回,是队已为空队,返回后knap10也结束

for(i=1;i<=ee;i++){

if(fabs(q[i].cw)<0.01) w=0.0;else w=q[i].cp/q[i].cw;//cw0w也为0,第一次大于mx=-1

if(q[i].i== (n+1))w=0.0;     //到达叶节点的w0,同上第一次大于mx=-1,往后不会

if(mx<w && q[i].flag<2) {mx=w; ff=i;}} //选择单位效益最好的优先出队

q[ff].flag+=2;                      //出队+2做标记,原13为已取

return(ff);}

void knap10(double m,int n)

{int j,f=0,e=0,beste=0;double bestp=0;

 enode.cw=enode.cp=0.0;enode.flag=enode.par=0;enode.i=0;q[e]=enode;

 while(enode.i<n){

     node.cw=enode.cw+w[enode.i+1];

         printf("----f=%d,e=%d,enode.i=%d,enode.cw=%9.2f",f,e,enode.i,enode.cw);

 if(node.cw<=m){node.cp=enode.cp+p[enode.i+1];

                        if(node.cp>bestp){bestp=node.cp;beste=e+1;}

                node.flag=1;node.par=f;node.i=enode.i+1;e++;q[e]=node;

 printf("\n***q[%d].i=%d,bestp=%9.2f,beste=%d  ",e,q[e].i,bestp,beste);  }

 if(bound(m,n,enode.i)>=bestp){

 node.cw=enode.cw;node.cp=enode.cp;node.flag=0;node.par=f;node.i=enode.i+1;

 e++;q[e]=node; }

 f=outnode(n,e);printf("oooq[%d].flag=%d",f,q[f].flag); if(f==-1) break;

 enode=q[f];printf("\nq[%d].i=%d,bestp=%9.2f,beste=%d  ",e,q[e].i,bestp,beste); }

  for(j=1;j<=n;j++){if(q[beste].flag==1 || q[beste].flag==3)

printf("choose %d",q[beste].i);beste=q[beste].par;}

 printf("\nMax=%9.2f)",bestp);}

int outnode(int n,int ee)

{int i,ff=-1;double w,mx=-1;//ff初值-1,若保持返回,是队已为空队,返回后knap10也结束

for(i=1;i<=ee;i++){

if(fabs(q[i].cw)<0.01) w=0.0;else w=q[i].cp/q[i].cw;//cw0w也为0,第一次大于mx=-1

if(q[i].i== (n+1))w=0.0;     //到达叶节点的w0,同上第一次大于mx=-1,往后不会

if(mx<w && q[i].flag<2) {mx=w;ff=i;}} //单位效益最好优先出队,flag>=2的也通过不选

q[ff].flag+=2; //出队+2做标记,原13为已取

return(ff);}

void knap10(double m,int n)

{int j,f=0,e=0,beste=0;double bestp=0;

 enode.cw=enode.cp=0.0;enode.flag=enode.par=0;enode.i=0;q[e]=enode;

 while(enode.i<n || f ){

     node.cw=enode.cw+w[enode.i+1];

         printf("----f=%d,e=%d,enode.i=%d,enode.cw=%9.2f",f,e,enode.i,enode.cw);

 if(node.cw<=m){node.cp=enode.cp+p[enode.i+1];

                        if(node.cp>bestp){bestp=node.cp;beste=e+1;}

                node.flag=1;node.par=f;node.i=enode.i+1;e++;q[e]=node;

 printf("\n***q[%d].i=%d,bestp=%9.2f,beste=%d  ",e,q[e].i,bestp,beste);

 }

 if(bound(m,n,enode.i)>=bestp){

node.cw=enode.cw;node.cp=enode.cp;node.flag=0;node.par=f;node.i=enode.i+1;

 e++;q[e]=node; }

 f=outnode(n,e);printf("oooq[%d].flag=%d",f,q[f].flag);

 if(f==-1) break;

 enode=q[f];printf("\nq[%d].i=%d,bestp=%9.2f,beste=%d  ",e,q[e].i,bestp,beste); 

 }

  for(j=1;j<=n;j++){

if(q[beste].flag==1 || q[beste].flag==3)printf("choose %d",q[beste].i);beste=q[beste].par;}

 printf("\nMax=%9.2f)",bestp);}

void knap11(int m,int n)//动态规划方法

{printf("m=%d,n=%d,w[n]=%d",m,n,w[n]);

int y=0,i=0,mm;mm=m;

for(y=0;y<w[n];y++) f[n][y]=0; for(y=w[n];y<=m;y++) f[n][y]=p[n];

for(y=0;y<=m;y++)printf("f[%d][%d]=%d  ",5,y,f[5][y]);

for(i=n-1;i>1;i--){

for(y=0;y<w[i];y++) {f[i][y]=f[i+1][y];printf("--f[%d][%d]=%d ",i,y,f[i][y]);}

for(y=w[i];y<=m;y++){ 

if(f[i+1][y]>f[i+1][y-(int)w[i]]+p[i])f[i][y]=f[i+1][y];else f[i][y]=f[i+1][y-(int)w[i]]+p[i];

printf(" **f[%d][%d]=%d \n",i,y,f[i][y]);}} if(m>=w[1]) if(f[2][m]>f[2][m-(int)w[1]]+p[1]) f[1][m]=f[2][m];else f[1][m]=f[2][m-(int)w[1]]+p[1];

printf(" &&f[%d][%d]=%d \n",1,mm,f[1][mm]);

for(i=1;i<n;i++) if(f[i][m]==f[i+1][m])x[i]=0;else {x[i]=1;m=m-w[i];}

printf("^^^m=%d,f[%d][m]=%d",m,n,f[n][m]);

if(f[n][m]!=0)x[n]=1;else x[n]=0;

for(i=1;i<=n;i++) printf("x[%d]=%d   ",i,x[i]);printf("\nMax=%d",f[1][mm]);

}

void main()

{ int i;

//if(!(knap3(s,n))) printf("No solution");

//printf(" max=%5.2f ",knap5(519,9));

//max=total=0;

//knap6(519,9,1);for(i=1;i<=9;i++) printf("\n(x[%d]=%d) ",i,x[i]);

//sort(9);for(i=1;i<=9;i++) printf("(%6.2f,%6.2f,%9.4f)",w[i],p[i],p[i]/w[i]);

//knap7(519,9,1);//knap7(6,2,1);

//knap8(519,9);

//for(i=1;i<=9;i++) printf("\n(x[%d]=%d) ",i,x[i]);

//knap10(519,9);

knap11(519,9);

}

//马的周游路线

#include <stdio.h>

int n=8;m=8; //8*8棋盘

int fx[9]={0,1,2,2,1,-1,-2,-2,-1},fy[9]={0,2,1,-1,-2,-2,-1,1,2},a[9][9];

int dep,x,y,count;

int check(int x,int y) //检查是否合法位置,超界或已有子为不合法

{ if(x>n ||y>m ||x<1||y<1 || a[x][y]>0) return(0); return(1);}

void output()  //送出一个答案

{count=count+1;printf("\n");

for(x=1;x<=n;x++){printf("\n"); for(y=1;y<=m;y++) printf(" %2d ",a[x][y]);}}

void find(int x,int y,int dep) //找(xy)的下一个位置

{int i,xx,yy;

//printf("y=%d,x=%d",y,x);getchar();

for(i=1;i<=8;i++){ xx=x+fx[i];yy=y+fy[i]; //找到下一个位置

if(check(xx,yy)= =1) //若下一位置合法,不合法无操作,再找下一个,共找8

{a[xx][yy]=dep;if(dep==n*m)output();else find(xx,yy,dep+1);a[xx][yy]=0;}}}

void main()

{ int i,j;

count=0;dep=1;x=1;y=1;if(x>n ||y>m ||x<1||y<1)printf("error");

for(i=1;i<=n;i++)for(j=1;j<m;j++)a[i][j]=0;

a[x][y]=1;find(x,y,2);

if(count==0)printf("No solution");else printf("count=%d",count);

}

//走迷宫问题

#include <stdio.h>

int maze[9][9]={{0,0,0,0,0,0,0,0,0},{0,0,0,0,0,0,0,0,0},{0,0,1,1,1,1,0,1,0},

{0,0,0,0,0,1,0,1,0},{0,0,1,0,0,0,0,1,0},{0,0,1,0,1,1,0,1,0},{0,0,1,0,0,0,0,1,1},

{0,0,1,0,0,1,0,0,0},{0,0,1,1,1,1,1,1,0}};int ma2[9][9];

int fx[5]={0,1,-1,0,0},fy[5]={0,0,0,-1,1};

struct {int x,y,pre;}sq[100];int qh,qe,i,j,k,total;

void outmaze(){int i,j;  //显示迷宫本身

for(i=1;i<=8;i++) {printf("\n");for(j=1;j<=8;j++) printf("%2d",maze[i][j]);}printf("\n");}

int checka(int i,int j)  //检查位置(i,j)是否合理

{int flag=1;if(i<1 || i>8 || j<1 || j>8)flag=0;

 if(maze[i][j]==1 || maze[i][j]==-1)flag=0;

 return(flag);}

int checkb(int i,int j,int k) //检查位置(i,j),沿fx[k],fy[k]指示的移动是否可行。

{int flag=1;i=i+fx[k];j=j+fy[k];if(i<1 || i>8 || j<1 || j>8)flag=0;

 if(ma2[i][j]!=0)flag=0;

 return(flag);}

void outq()  //输出宽度第一找到的走出路线

{printf("(%d,%d) ",sq[qe].x,sq[qe].y);

while(sq[qe].pre!=0){qe=sq[qe].pre;printf("-->(%d,%d)",sq[qe].x,sq[qe].y);}}

void outb()//输出深度第一找到的走出路线,和被深度搜索修改的矩阵

{int i,j;for(i=1;i<=8;i++){printf("\n");

       for(j=1;j<=8;j++) if(ma2[i][j]==3){printf("V");total++;}else printf("*");

}printf("total=%d\n",total);

for(i=1;i<=8;i++){printf("\n");for(j=1;j<=8;j++) printf("%2d",ma2[i][j]);}}

void search()  //宽度第一搜索

{ qh=0;qe=1;maze[1][1]=-1;sq[1].pre=0;sq[1].x=1;sq[1].y=1;

while(qh != qe){qh++;

for(k=1;k<=4;k++){i=sq[qh].x+fx[k];j=sq[qh].y+fy[k];

      if(check(i,j) == 1){qe++;sq[qe].x=i;sq[qe].y=j;sq[qe].pre=qh;maze[i][j]=-1;

          if(sq[qe].x==8 && sq[qe].y==8){outq();return;}

  }}}

printf("No solution");

}                                          

void searchb(int i,int j) //深度第一搜索,递归实现

{int k,newi,newj;

for(k=1;k<=4;k++)if(checkb(i,j,k) == 1){

newi=i+fx[k];newj=j+fy[k];ma2[newi][newj]=3;

if(newi==8 && newj==8)outb();else searchb(newi,newj);}

ma2[i][j]=2;}

void main()

{  int i,j;for(i=1;i<=8;i++)for(j=1;j<=8;j++)ma2[i][j]=maze[i][j];

   outmaze();search();

   total=0;ma2[1][1]=3;searchb(1,1);}

#include "stdio.h" //计算机常用算法与程序设计教程,

void main()        //20页例2.3,  1和2属于A,2x+3y属于A,生成A

{ int n,t,k,i,h,j,a[3000];

n=30;a[1]=1;a[2]=2; t=2;

for(k=3;k<=1000;k++){

h=0;

for(i=2;i<=t;i++){

for(j=1;j<=i-1;j++)

if (k == 2*a[i]+3*a[j] || k == 2*a[j]+3*a[i]){

h=1;t++;a[t]=k;

if (k == 2*a[i]+3*a[j]) {printf("%3d (%3d,i=%3d,j=%3d)  ",k,t,a[i],a[j]);break;}

if (k == 2*a[j]+3*a[i]) {printf("%3d (%3d,j=%3d,i=%3d)  ",k,t,a[j],a[i]);break;}

}

if(h==1) {printf("h=%d,j=%d,i=%d\n",h,j,i);break;}

}

if(t==n)break;

}

      printf("end");getchar();

} //程序运行,其中t在循环中变大,break跳出不错。

#include "stdafx.h"  //算法设计与应用,118页,(13)题

#include "stdio.h"

int main()

{  int a,b,c,d,e;

   for(a=1;a<=5;a++)

   for(b=1;b<=5;b++)

   for(c=1;c<=5;c++)

   for(d=1;d<=5;d++)

   for(e=1;e<=5;e++){

   if(a==b || a==c||a==d || a==e)continue;

   if(b==c|| b==d|| b==e)continue;

                      if(c==d || c==e ||d==e)continue;

   if (!((b==3 &&c!=5) ||(b!=3 && c==5))) continue;

                      if (!((d==2 &&e!=4) ||(d!=2 && e==4))) continue;  

                      if (!((b==1 &&e!=4) ||(b!=1 && e==4))) continue;  

                      if (!((c==1 &&b!=2) ||(c!=1 && b==2))) continue;   

                      if (!((d==2 &&a!=3) ||(d!=2 && a==3))) continue

   printf("(%d,%d,%d,%d,%d)\n",a,b,c,d,e);

   } 

getchar();return 0;

}   //运行得到答案:3,2,5,1,4

#include <fstream>  //算法设计与应用,吕国英书,119页题(20

using namespace std;

void main()

{ int i,j,k,i1,j1,k1,t,s,b[10];

ofstream outFile;

outFile.open("result.txt");

for(t=0;t<=9;t++)b[t]=0;

for(i=12;i<=98;i++)  //二位数i

for(j=123;j<=987;j++){  // 三位数j

for(t=0;t<=9;t++)b[t]=0;     

s=0;k=i*j;i1=i;j1=j;k1=k;  // 四位数k=i*j

if(k>9999)continue;

do {b[i1%10]++;}while(i1=i1/10); // 取得组成i,j,k的各位数字

do {b[j1%10]++;}while(j1=j1/10);

do {b[k1%10]++;}while(k1=k1/10);

if(b[0] != 0) continue;  //不能有0出现

for(t=1;t<=9;t++)if(b[t] !=1) {s=1;break;}  // 其他数字都必须各是1

if(s)continue;

outFile<<i<<"*"<<j<<"="<<k<<",";}}//输出为:12*483=5796,18*297=5346,27*198=5346,28*157=4396,39*186=7254,42*138=5796,

48*159=7632

#include "stdio.h"//201页例2走迷宫问题,注意矩阵下标从1开始

Int maze[9][9]={{0,0,0,0,0,0,0,0,0},{0,0,0,0,0,0,0,0,0},{0,0,1,1,1,1,0,1,0},

{0,0,0,0,0,1,0,1,0},{0,0,1,0,0,0,0,1,0},{0,0,1,0,1,1,0,1,0},{0,0,1,0,0,0,0,1,1},{0,0,1,0,0,1,0,0,0},{0,0,1,1,1,1,1,1,0}};

int fx[5]={0,1,-1,0,0},fy[5]={0,0,0,-1,1};//迷宫与可行方向

struct {int x,y,pre;}sq[100]; //走迷宫的步骤序列

int qh,qe,i,j,k;

int check(int i,int j) //检查位置i,j是否合法

{ int flg=1;

if(i<1 || j<1 || i>8 || j>8)flg=0; //出界

if(maze[i][j]==1 || maze[i][j]==-1)flg=0; //原有障碍,或已走过

return(flg);

}

void outsq()//输出找到的走迷宫的步骤序列

{ printf("(%d,%d),",sq[qe].x,sq[qe].y);

while(sq[qe].pre != 0){qe=sq[qe].pre;printf("(%d,%d),",sq[qe].x,sq[qe].y);}

}

void main()

{   int i,j; //先打印迷宫本身看一下

for(i=1;i<=8;i++){for(j=1;j<=8;j++) printf("%3d",maze[i][j]);printf("\n");}

qh=0;qe=1;maze[1][1]=-1;sq[1].pre=0;sq[1].x=1;sq[1].y=1; //初始化,从1,1开始走

while(qh!= qe){qh++;

             for(k=1;k<=4;k++){

 i=sq[qh].x+fx[k];j=sq[qh].y+fy[k];

 if(check(i,j)){ //宽度第一搜索,

 qe++;sq[qe].x=i;sq[qe].y=j;sq[qe].pre=qh;maze[i][j]=-1;

 if(sq[qe].x==8 && sq[qe].y==8){outsq();return;}

}}}//注意sq中存放有访问过的所有方格,输出时按pre指示给出找到的路。

printf("No Solution\n");    

}

#include <iostream> //223页例10,输出n的全排列

using namespace std;

int p=0;  // 生成排列个数,1n!,数组a中生成,

int n,a[100],d[100];  //数组d记第n个元素是否使用,1表用,0表未用

void outp() // 输出第p个排列后换行

{int i;cout<<"("<<p<<")";for(i=1;i<=n;i++) cout<<a[i];cout<<endl;}

void ttry(int k) // 填入第k个数,递归工作

{ int i;cout<<k<<endl; //此处出k,记录调用情况,为理解程序加入的。

for(i=1;i<=n;i++){

if(d[i]==0){a[k]=i;d[i]=1;} else continue;

if(k<n) ttry(k+1); else {p++;outp();}

d[a[k]]=0;

}

}

int main()   //主程序,从填入第一个数字开始,以n=3为例,出123 1123  

{ int i;   // 3 2132  23 3213  3 4231  23  5312  

n=3;for(i=1;i<=n;i++) d[i]=0;  // 3 6321结束

ttry(1);                    //,以n=2为例,出12 112  2  (2) 21结束

return(1);                  

}

void btry(int t) //224页例11,例10另一解法,本程序对应ttry, 其余程序相同不重复 

{ int i;cout<<t<<endl;

    if(t>n) {cout<<"-----";p++;outp();} else{

for(i=t;i<=n;i++){swap(t,i);btry(t+1);swap(t,i);}

}

}

int main()                        //,以n=3为例,出12341123  342132

{ int i; n=3;for(i=1;i<=n;i++) a[i]=i; //234 3213  34 4231   234 5321

    btry(1);return(1);                 // 31 6312结束

}                                // 以n=2为例,出123,(1)12  23  (2) 21结束

#include <iostream>   //247页题(8),连续翻币5

using namespace std;

void dtob(int m,int s[],int n)   //十进制数m,转换为n位二进制数组s

{int i; for(i=n;i>=1;i--) s[i]=0; i=1;do {s[i++]=m%2;}while(m=m/2);}

void disp(int s[],int n)      //显示n位二进制数组s

{int i;cout<<"(";for(i=n;i>=1;i--)cout<<s[i];cout<<")"<<endl;}

void abcopy(int a[],int b[],int n)  //n位二进制数组a,拷贝到b

{int i;for(i=0;i<=n;i++) b[i]=a[i];}

int btod(int s[],int n) //n位二进制数组s,转换为十进制数返回

{int i,m,t;t=1;m=s[1];for(i=2;i<=n;i++) {t=t*2;m=t*s[i]+m;}  return m;}

int insert(int m,int a[],int n)                 //整数m排序插入数组a

{ int i;for(i=n;i>=0;i--){if(a[i]==m)return(0); //有不必插返回0,没有插入返回1,未用

if(a[i]>m)a[i+1]=a[i];

if(a[i]<m) {a[i+1]=m;return(1);}}}

int append(int m,int a[],int n) //检查整数m是否在数组a中,在返0,不在接后面返1

{ int i;for(i=n-1;i>=1;i--)if(a[i]==m)return(0);a[n]=m;return(1);}

void main()

{ int i,j,k,n,m,st,ed,t,ans,a[10],b[10],c[100];

n=7;t=0;st=ed=1;ans=0;

for(i=1;i<=n;i++)a[i]=1;

    c[ed++]=btod(a,n);

while(st != ed){

m=c[st++];dtob(m,a,n);

cout<<"st="<<st<<"ed="<<ed<<endl;cout<<"a=";disp(a,n);cout<<"b=";disp(b,n);

    for(i=1;i<=n-4;i++){

abcopy(a,b,n);

      for(j=i;j<=i+4;j++) if(b[j]==1) b[j]=0;else b[j]=1;

     cout<<"i="<<i<<"j="<<j;cout<<"a=";disp(a,n);cout<<"b=";disp(b,n);

    m=btod(b,n);if(m==0) {ans=1;cout<<"ans="<<ans<<endl;return;}        

            t=append(m,c,ed);if(t==1){t=0;ed++;}

    for(k=1;k<ed;k++) cout<<"("<<k<<","<<c[k]<<")";

}//运行通过,n=5显然,n=6时生成节点4个:63,32,1,30, n=7时生成8个:

}    // 127,96,65,3,94,28,61,34, n=8,时16个:255,224,193,131,7,222,156,24, 

} //189,57,123,162,38,100,69,90,n=9时32个:511,488,均无解。n=10时1023,992等有解。

#include <iostream>  //228页例14,作业调度问题

using namespace std;

int f1=0,f2[100]={0};

int job[100][2],x[100],bestx[100],bestf,n; //数组x模拟生成全排列

void swap(int i,int j){int t;t=x[i];x[i]=x[j];x[j]=t;} //交换一次生成一个新的排列

void ttry(int i) // 第i个作业

{ int j;  //现看一下当前选择的顺序,调试用

cout<<"(i="<<i<<")(";for(j=1;j<=n;j++) cout<<x[j]<<" ";cout<<")"<<endl;

if(i==n+1){for(j=1;j<=n;j++) bestx[j]=x[j];bestf=f2[n];} //找到解,这里n,原i,错,

else for(j=i;j<=n;j++){                            //已改n,改i-1也可

        f1=f1+job[x[j]][1];cout<<"f1="<<f1<<" "; //f1f2是加工时间

if(f2[i-1]>f1) f2[i]=f2[i-1]+job[x[j]][2];else f2[i]=f1+job[x[j]][2];

cout<<"f2["<<i<<"]="<<f2[i]<<" ";

if(f2[i]<bestf){ swap(i,j);ttry(i+1); swap(i,j);}

f1=f1-job[x[j]][1];}

}

int main()  //运行举例,n=2时,出(1)(12f1=3,f2[1]=7,f1=5,f2[2]=15

{   int i;n=3;               // (2) (21)

 f1=2,f2[1]=10,f1=5,f2[2]=14,ans=21,bestf=14

job[1][1]=3;job[1][2]=4;job[2][1]=2;job[2][2]=8; job[3][1]=5;job[3][2]=10;bestf=32767;

for(i=1;i<=n;i++) x[i]=i;

ttry(1);                       //n=3时,依次查过123, 用时25132,用时26

cout<<endl<<"ans=";for(i=1;i<=n;i++) cout<<bestx[i];cout<<endl;

cout<<"bestf="<<bestf<<endl;         //213,231, 都用时24321,312都用时27

}                                      //最后顺序ans=213,时间bestf=24

原创粉丝点击