//模仿人工的大整数加法
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++){ //从2至9000逐一检查。
s=1;k=0; //第一个因子1不再求,直接列入和s中。
for(j=2;j<=i/2;j++) if(i%j ==0){s=s+j;a[k++]=j;} //从2至i/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; //m是n因子时存放于数组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页例8,9
#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; //如(1)118262 =139854276……
}
if(k==9){num++;printf("num=%3d, x=%6d, x*x=%10d\n",num,x,y1);}
}} //共找到83组,(1)10124*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;//log是e为底
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页例15,265页节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 输出,fm2第2小
{ 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]; //字符方式给出整数n,0位不用,如“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页例15,265页节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)//完善knap5,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;}
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;//cw为0时w也为0,第一次大于mx=-1
if(q[i].i== (n+1))w=0.0; //到达叶节点的w为0,同上第一次大于mx=-1,往后不会
if(mx<w && q[i].flag<2) {mx=w; ff=i;}} //选择单位效益最好的优先出队
q[ff].flag+=2; //出队+2做标记,原1现3为已取
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;//cw为0时w也为0,第一次大于mx=-1
if(q[i].i== (n+1))w=0.0; //到达叶节点的w为0,同上第一次大于mx=-1,往后不会
if(mx<w && q[i].flag<2) {mx=w;ff=i;}} //单位效益最好优先出队,flag>=2的也通过不选
q[ff].flag+=2; //出队+2做标记,原1现3为已取
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) //找(x,y)的下一个位置
{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; // 生成排列个数,1到n!,数组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 (1)123
{ int i; // 3 (2)132 23 (3)213 3 (4)231 23 (5)312
n=3;for(i=1;i<=n;i++) d[i]=0; // 3 (6)321结束
ttry(1); //,以n=2为例,出12 (1)12 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为例,出1234(1)123 34(2)132
{ int i; n=3;for(i=1;i<=n;i++) a[i]=i; //234 (3)213 34 (4)231 234 (5)321
btry(1);return(1); // 31 (6)312结束
} // 以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<<" "; //f1、f2是加工时间
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)(12)f1=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, 用时25,132,用时26
cout<<endl<<"ans=";for(i=1;i<=n;i++) cout<<bestx[i];cout<<endl;
cout<<"bestf="<<bestf<<endl; //213,231, 都用时24,321,312都用时27
} //最后顺序ans=213,时间bestf=24