i=1;a[i]=0; k=1; while(1) {t=1;
for(j=1;j
if(a[j] && a[j]==a[i]) {t=0;break;} // 非零元素相同,则返回 if(t && k==n-m && i==n) // 已取n 个值且0的个数为n-m时输出解 {s++;
for(j=1;j<=n;j++) printf(\ printf(\
if(s==0) printf(\ }
if(t && (k if(k else a[i]=1; // 若0的个数已达到n-m,则不再取0了 continue; } while(a[i]==n) i--; // 调整或回溯或终止 if(i>0) {if(a[i]==0) k--; // 改变取值为0的元素值前先把0的个数k减1 a[i]++; } else break; } printf(\} 5-10 8对夫妇特殊的拍照 一对夫妇邀请了7对夫妇朋友来家餐聚,东道主夫妇编为0号,其他各对按先后分别编为1,2,…,7号。 餐聚后拍照,摄影师要求这8对夫妇男左女右站在一排,东道主夫妇相邻排位在横排的正中央,其他各对排位,1号夫妇中间安排1个人,2号夫妇中间安排2个人,依此类推。 共有多少种拍照排队方式? 1. 设计要点 在n组每组2个相同元素(相当于n对情侣),a数组从0取到2n-1不重复,对n同余的两个数为一对编号:余数为0的为0号(即东道主),余数为1的为1号,…,余数为n-1的为n-1号。 例如,n=4,数组元素为0与4,对4同余,为一对“0”; 1与5对4同余,为一对“1”;一般地, i与4+i对4同余,为一对i,(i=0,1,2,3)。 返回条件修改为(当j a(j)=a(i) or a(j)%n=a(i)%n and (a(j)>a(i) or a(j)+1!=i-j) 其中a(j)=a(i),为使a数组的2n个元素不重复取值; a(j)%n=a(i)%n and a(j)>a(i),避免同一对取余相同的数左边大于右边,导致重复; a(j)%n=a(i)%n and a(j)+1!=i-j,避免同一对数位置相差不满足题意相间要求。 例如,a(j)=0时,此时a(i)=n,为0号情侣,位置应相差1(即中间没有人),即i-j=1。 a(j)=1时,此时a(i)=n+1,为1号情侣,位置应相差2(即中间有1人),即i-j=2。 这些都应满足条件a(j)+1=i-j。如果a(j)+1!=i-j,不满足要求,返回。 设m=2n,若满足条件(g>0 and i=m and a(1)%n 2. 程序实现 // 8对夫妇拍照 #include {int i,j,g,n,m,s,a[20]; printf(\scanf(\ m=2*n; i=1;a[i]=0;s=0; while(1) {g=1; for(j=1;j if(a[j]==a[i] || a[j]%n==a[i]%n && (a[j]>a[i] || a[j]+1!=i-j)) {g=0;break;} // 出现相同元素或同余小在后时返回