您的位置:首页 > 其它

分治与递归——循环赛日程表

2015-10-30 18:57 309 查看
参考下~~~原文地址:分治与递归——循环赛日程表作者:天书zdilby
问题描述:有n个运动员进行循环赛,要求设计满足一下要求的日程表

1、
每两人必须比赛一次且只比赛一次

2、
每个选手每天只能比赛一次

3、
要求比赛时间尽可能短(即n为偶数时比赛n-1天,n为奇数时比赛n天)

一、分治法

算法思想,先算n/2的日程表,然后将循环赛日程表左上复制到右下,左下复制到右上,得到n的日程表,递归实现

实现代码:

//循环赛日程表

#include
<stdio.h>

#define N
1000

int
a

;

int
b
;

inline
bool odd(int n)

{

return n & 1;

}

void
copy(int n)//将左上角抄到右下角,将右上角加n/2后抄到左下角,将左下角抄到右上角

{

int m=n/2;

int i,j;

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

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

{

a[i][j+m]=a[i][j]+m;//将左上角抄到右下角

a[i+m][j]=a[i][j+m];//将右上角加n/2后抄到左下角

a[i+m][j+m]=a[i][j];//将左下角抄到右上角

}

}

void
copyodd(int n)//n/2为奇数时的复制,让轮空选手与下一个为参赛选手进行比赛

{

int m=n/2;

int i,j;

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

{

b[i]=m+i;

b[m+i]=b[i];

}

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

{

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

{

if(a[i][j]>m)

{

a[i][j]=b[i];

a[m+i][j]=(b[i]+m)%n;

}

else

a[m+i][j]=a[i][j]+m;

}

for(j=2;j<=m;++j)

{

a[i][m+j]=b[i+j-1];

a[b[i+j-1]][m+j]=i;

}

}

}

void
makecopy(int n)

{

if(n/2>1 &&
odd(n/2)) copyodd(n);

else copy(n);

}

void
tour(int n)

{

if(n==1)

{

a[1][1]=1;

return;

}

if(odd(n))

{

tour(n+1);//当n为奇数,就设置一个虚拟的n+1,然后就有偶数个人了。。。。和一休的那个分马很像啊

return;

}

tour(n/2);

makecopy(n);

}

void
out(int n)

{

if(n==1)

{

printf("1n");

return;

}

int i,j;

int m;

if(odd(n))

m=n+1;

else

m=n;

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

{

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

{

if(a[i][j]>n)//当比赛日程是与那位虚拟出来的n+1号选手比赛时,输出0,代表轮空

printf("0 ");

else

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

}

printf("n");

}

}

int
main()

{

int n;

while(scanf("%d",&n),n)

{

tour(n);

out(n);

}

return 0;

}

2、多边形法(我的实现),通过旋转多边形的一种巧妙方法

//循环赛日程表

#include
<stdio.h>

#define N
1000

int
a

;

inline
bool odd(int n)

{

return n & 1;

}

void
init()

{

int i;

for(i=0;i<N;++i)

a[i][0]=i;

}

void
tour(int n)

{

if(odd(n))

tour(n+1);

else

{

int i,j,k;

int m=n-1;

int p,q;

for(i=1;i<=m;++i)//第一天到第n-1天

{

j=i;

p=j+1;

if(p>m) p=p-m;

a[p][i]=n;

a
[i]=p;

for(k=0;k<=n/2-2;++k)

{

q=j-k;

p=j+k+2;

if(p>m) p-=m;

if(q<=0) q+=m;

a[q][i]=p;

a[p][i]=q;

}

}

}

}

void
out(int n)

{

if(n==1)

{

printf("1n");

return;

}

int i,j;

int m;

if(odd(n))

m=n+1;

else

m=n;

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

{

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

{

if(a[i][j]>n)

printf("0 ");

else

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

}

printf("n");

}

}

int
main()

{

int n;

init();

while(scanf("%d",&n),n)

{

tour(n);

out(n);

}

return 0;

}

4、
多边形法(王晓东算法设计与分析教材上的实现,比较费解,比较牛逼)
#include
<stdio.h>

#define N
1000

int
a

;

int
b
;

inline
bool odd(int n)

{

return n & 1;

}

void
init()

{

int i;

for(i=0;i<N;++i)

a[i][0]=i;

}

void
tour(int n)

{

a
[1]=n;

if(n==1) return;

int m=odd(n) ? n : n-1;

int i,j,k,r;

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

{

a[i][1]=i;

b[i]=i+1;

b[m+i]=i+1;

}

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

{

a[1][i+1]=b[i];

a[b[i]][i+1]=1;

for(j=1;j<=m/2;++j)

{

k=b[i+j];

r=b[i+m-j];

a[k][i+1]=r;

a[r][i+1]=k;

}

}

}

void
out(int n)

{

if(n==1)

{

printf("1n");

return;

}

int i,j;

int m;

if(odd(n))

m=n+1;

else

m=n;

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

{

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

{

if(a[i][j]>n)

printf("0 ");

else

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

}

printf("n");

}

}

int
main()

{

int n;

init();

while(scanf("%d",&n),n)

{

tour(n);

out(n);

}

return 0;

}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: