// --------------------------------------------------------------////kamm(德语意为梳子)////用M标记评价长度L的完美标尺//编译:cc-o kamm kamm.c-o//参数M和L可以在对话框中输入(#define DIALOG)//或从文件“kamm.param”读取(#define noDIALOG)//文件“kamm.param”的格式:////M1 L1级//M2平方米////锰-Ln// 0////M=0终止程序。//kamm检查标记<10和>L-10是否//之前计算过,可能顺序不同。////找到一个解决方案后终止:#define FIRST_ONLY//要获取所有解决方案:#define notFIRST_ONLY////如果需要所有解决方案,可能需要//增加MAXPROT和MAXMARK,否则协议溢出。////在noFIRST_ONLY模式下,给出了两个计数://第一个数字:计算所有溶液。//括号中:对称解只计算一次。////#define RESULTS_ONLY:只打印计数。//否则打印所有解决方案,对称解决方案为//标记为“<<<sym”。////克劳斯·纳格尔2003/02/10//修订于2005/01/19//修订日期:2009/03/23//// --------------------------------------------------------------#定义对话#定义notFIRST_ONLY#定义notRESULTS_ONLY#定义MAXPROT 1000000#定义MAXMARK 22#包括#包括#包括#包括整数L;整数M;int Protocoll[MAXPROT][MAXMARK-2];//检查等效解决方案int保护指针;int Sol_counter;//溶液计数器(等效溶液一次)int Sol_counter1;//溶液计数器(非对称两次)int限制;//L-B(M,2)int循环,循环1;//计数递归调用(单位,十亿=1.e9)int perm[2000];int停止;整数标记[0x100000];双桑[100];int schonda;//------------------使Luschny集合------------------无效mach_lus(int k,int a[],int lus[]){整数i,j;对于(i=0;i<=L;i++)lus[i]=0;对于(i=1;i<k;i++)对于(j=0;j<i;j++){lus[abs(a[i]-a[j])]++;}}//------------------对称------------------int sym(int a[]){int i,j,索引[1100];memset(索引,0,索引大小);对于(i=0;i<M;i++)索引[a[i]]=1;//用于排序j=L;对于(i=0;i<j;i++){如果(索引[i]!=索引[j--])返回2;}返回1;}//------------------代表------------------//rep:从类中确定唯一的代表//等效解决方案并将其写入协议指针void rep(int a[],int指针){int i,j,k,b[100],索引[1100];memset(索引,0,索引大小);对于(i=0;i<M;i++)指数[a[i]]++;j=0;k=0;对于(i=1;i<=L;i++){if(索引[i]){b[M-2-k]=协议[pointer][k]=i-j;j=i;k++;}}对于(i=0;i<M-2;i++){如果(b[i]<Protocoll[pointer][i])转到b_is_smaller;if(协议[pointer][i]<b[i])返回;}回报;b_is较小:对于(i=0;i<M-2;i++)Protocoll[指针][i]=b[i];回报;}//------------------密钥------------------int键(int k,int a[]){整数i,x,m;x=0;m=1<<19;对于(i=0;i<k;i++){如果(a[i]>9&&a[i]<L-9)返回(-1);如果(a[i]<10){x |=1<<a[i];}如果(a[i]>L-10){x |=m>>(L-a[i]);}}返回(x);}//------------------反转------------------int反转(int x){整数y,m;y=0;m=1<<19;同时(x){如果(x&1)y|=m;m>>=1;x>>=1;}收益(y);}//------------------设置标记------------------无效集合标记(int k,int a[]){整数x;x=键(k,a);如果(x!=-1){标记[x]|=(1<停止!=0)返回;x=键(k,a);如果(k<1&&x!=-1&&mark[x]){回报;}//确定所有可测量的长度//过量(长度可以过多地测量)总和=0;对于(i=1;i<=L;i++){如果(lfeld[i]>1)和+=lfeld[i]-1;}如果(sum>Limit)返回;//并非所有长度都能达到//寻找最大缺失长度for(lang=L-2;lang>1;lang--)//标记0,1,L是固定的{如果(lfeld[lang]==0)转到weiter;}//解决方案,因为未找到缺失的长度代表(a,指针);//在协议中输入解决方案对于(i=0;i<Prot_pointer;i++){对于(j=0;j<M-2;j++){如果(Protocoll[Prot_pointer][j]!=Protocoll[i][j])中断;}if(j==M-2)//条目i和Prot_pointer之间没有偏差。//解决方案并不新鲜。{schonda++;回报;}}//协议中未找到等效解决方案指针++;if(保护指针>=MAXPROT){perror(“Protocoll溢出”);退出(0);}memset(索引,0,索引大小);对于(i=0;i<M;i++)索引[a[i]]=1;//用于排序++溶液计数器;syma=sym(a);Sol_counter1+=syma;#ifndef结果_仅printf(“>”);对于(i=0;i<=L;i++)if(索引[i])printf(“%4d”,i);printf(“%8d”,Sol_counter);如果(syma==1)打印f(“<<<sym”);printf(“\n”);#结束语#ifdef第一个_唯一停止=1;#结束语回报;韦特:memset(索引,0,索引大小);对于(i=0;i<k;i++){p=a[i]+lang;如果(p<L){指数[p]++;}p=a[i]-lang;如果(p>0){指数[p]++;}}//对于所有符合“lang”的分数对于(ii=3;ii<=L;ii++){i=烫发[ii];if(索引[i]){a[k]=i;成员(lus,lfeld,sizeof lus);对于(j=0;j<k;j++){lus[abs(i-a[j])]++;}普鲁夫(k+1,a,lus);//这是递归调用!!!!!!!!如果(k<9)设置标记(k+1,a);}}}//------------------主程序------------------整型main(){结构时间值tp;结构时区tzp;int a[100],lus[1100],i,sec,usec,t;双zeit;#ifndef对话文件*fd;#结束语printf(“kamm,编译%s%s\n”,__DATE__,__TIME__);#ifndef对话fd=fopen(“kamm.param”,“r”);if(!fd)perror(“文件kamm.param丢失”);#结束语schonda=0;安芳:#ifdef对话printf(“M und L?”);扫描(“%d”,&M);如果(M==0)退出(0);扫描(“%d”,&L);#结束语#ifndef对话fscanf(fd,“%d”,&M);如果(M==0)退出(0);fscanf(fd,“%d”,&L);#结束语memset(标记,0,标记大小);极限=(M-1)*M/2-L;t=0;a[t++]=0;//长度L需要标记0和La[t++]=L;a[t++]=1;//长度L-1无通用性损失马赫_卢斯(3,a,lus);//从外部加工开始生成排列//朝向中心对于(i=0;i<=L;i++){如果(i&1)perm[i]=L-(i>>1);否则perm[i]=i>>1;}Sol_counter=0;溶液计数器1=0;指针=0;memset(Protocol,0,Protocol大小);memset(sanz,0,sizeof sanz);回路=回路1=0;停止=0;gettimeofday(&tp,&tzp);秒=tp.tv_sec;usec=tp.tv_usec;普鲁夫(t,a,lus);gettimeofday(&tp,&tzp);zeit=(tp.tv_sec-sec)+(tp.tv-usec-usec)/10000000;printf(“\n%6d%09d递归调用%12.3lf秒\n”,Loops1,Loops,zeit);#ifdef第一个_唯一if(Sol_counter)printf(“M=%3d L=%4d至少有一个解决方案”,M,L);其他的printf(“M=%3d L=%4d没有解决方案”,M,L);#结束语#如果FIRST_ONLYprintf(“M=%3d L=%4d有%8d(%8d)个解决方案”,M,L,2*Sol_counter,Sol_counter1);#结束语printf(“遇到现有解决方案的%8次。\n”,schonda);#ifdef测试对于(i=3;i<=M;i++){printf(“%3d%12.0lf\n”,i,sanz[i]);}#结束语去安防;}