问题描述:
假设我们有 2n 张牌,它们以 1, 2, ..., n, n+1, ..., 2n 编号并在开始时保持着这种顺序。一次洗牌就是将牌原来的次序变为 n+1, 1, n+2, 2, ..., 2n, n,也就是将原来的前 n 张牌放到位置 2, 4, ..., 2n,并且将余下的 n 张牌按照他们原来的次序放到奇数位置 1, 3, ..., 2n-1。已经证明对于任何一个自然数 n,这 2n 张牌经过一定次数的洗牌就回到原来的次序。但我们不知道对于一个特定的 n,需要几次洗牌才能将牌洗回原来的次序。
输入:
牌张数的一半n,即初始情况下一共有2n张牌
输出:
将牌洗回原来的次序所需要的洗牌次数
解析:
我解决了这个问题,程序如下:
注意:n不能大于500,否则你就得改数组A和B的大小
#include <stdio.h>
int A[1000],B[500]
void main()
{
int m,n,i
int flag(int)
void exchange(int)
printf("input n:")
scanf("%d",&n)
for(i=0,m=n*2i<mi++) A[i]=i
i=0
do {exchange(n)i++}
while(flag(m))
printf("Times: %d",i)
}
void exchange(int n)
{
int i
for(i=0i<ni++)
B[i]=A[i+n]
for(i=n-1i>=0i--)
A[i*2+1]=A[i]
for(i=0i<ni++)
A[i*2]=B[i]
}
#include<stdio.h>#include<stdlib.h>
#include<time.h>
int n,a[20],b[20],c[20],n2
void init()
{int i,j,k,t
for(i=0i<n2i++)
a[i]=i+1
srand(time(0))
for(i=0,j=n2i<jj--)
{k=rand()%j
t=a[j-1]a[j-1]=a[k]a[k]=t
}
for(i=0i<n2i++)
c[i]=a[i]
}
void prt()
{for(int i=0i<n2i++)
{printf("%3d",a[i])
if(i==n-1)printf(" ||")
}
printf("\n")
}
void work()
{int i,t
for(i=1i<n2-1i++)
{t=i<n?i+i:(i+i)%n2+1
b[t]=a[i]
// printf("b[%d]=a[%d]\n",(i+i)%n2+1,i)
}
for(i=1i<n2-1i++)
a[i]=b[i]
}
bool done()
{for(int i=1i<n2i++)
if(a[i]!=c[i])return false
return true
}
int main()
{scanf("%d",&n)
n2=n+n
init()
prt()
do
{work()
prt()
}while(!done())
return 0
}
欢迎分享,转载请注明来源:内存溢出
评论列表(0条)