免费注册 查看新帖 |

Chinaunix

  平台 论坛 博客 文库
最近访问板块 发新帖
楼主: nickoal
打印 上一主题 下一主题

[算法] 赛程安排的算法 [复制链接]

论坛徽章:
0
21 [报告]
发表于 2005-05-10 17:29 |只看该作者

赛程安排的算法

算法不是太优,不过应该对.如果还不是联赛的算法,......我就不知道怎么比法了.

int n=20;
int i,j,k;
struct pair{
        int a;
        int b;
};

int compare(struct pair *y, int a, int b)
{
        for (i=0;i<n/2;i++){
                if (y.a==a || y.b==a || y.a==b || y.b==b)
                        return 0;
        }
        return 1;
}

main(){
        int m=n*(n-1)/2;
        struct pair y[n/2], x[m];

        k=0;
        for (i=1;i<=n;i++)
                for (j=i+1;j<=n;j++){
                        x[k].a=i;
                        x[k].b=j;
                        k++;
                }

        for (i=0;i<m;i++){
                k=0;
                for (j=0;j<n/2;j++){
                        y[j].a=0;
                        y[j].b=0;
                }

                j = 0;
                while (j<m){
                        while (j<m && x[j].a==-1) j++;
                        if (j>;=m) break;
                        if (x[j].a!=-1 && compare(y, x[j].a, x[j].b)){
                                y[k].a = x[j].a;
                                y[k].b = x[j].b;
                                printf("%d-%d, ", x[j].a, x[j].b);
                                x[j].a = -1;
                                k++;
                        }
                        j++;
                }
                if (k)        printf("\n";
        }
}

论坛徽章:
0
22 [报告]
发表于 2005-05-10 18:02 |只看该作者

赛程安排的算法

to narkissos:
我把你的结果贴在下面了(我把你的n改成6)

  1. sh-2.05b$ ./c5
  2. 1-2, 3-4, 5-6,
  3. 1-3, 2-4,
  4. 1-4, 2-3,
  5. 1-5, 2-6,
  6. 1-6, 2-5,
  7. 3-5, 4-6,
  8. 3-6, 4-5,
复制代码

下面是我今天上午的结果和实现代码

  1. sh-2.05b$ ./c3 6
  2. A ->; B,C ->; D,E ->; F,
  3. A ->; C,B ->; D,F ->; E,
  4. A ->; D,B ->; E,C ->; F,
  5. A ->; E,B ->; F,D ->; C,
  6. A ->; F,B ->; C,D ->; E,
  7. B ->; A,C ->; E,D ->; F,
  8. C ->; A,D ->; B,
  9. C ->; B,D ->; A,
  10. E ->; A,F ->; B,
  11. E ->; B,F ->; A,
复制代码


  1. include <stdio.h>;
  2. #include <stdlib.h>;
  3. #define SIZE 100
  4. void
  5. resume(char *per,int num)
  6. {
  7.     int i;  

  8.     for(i =0; i < num; i++)
  9.         per[i] = i + 'A';
  10. }

  11. int
  12. main(int argc,char **argv)
  13. {
  14.     int num,i,j,k=0,n=1,m;
  15.     char flag[SIZE][SIZE];
  16.     char per[SIZE];

  17.     num = atoi(argv[1]);
  18.     for(i = 0; i < num ; i++)
  19.         flag[i][i] = -1;
  20.     resume(per,num);
  21.     while(k < num*(num-1)/(num/2)) {
  22.         for(i = 0; i<num ;i++) {
  23.             if (per[i] != -1) {
  24.                 for(n>;i ? (j=n):(j=i),m=0; (per[i] != -1)&& (m<num); j==num-1 ? (j=0):(j++),m++)
  25.                     if(flag[i][j] != -1 && per[j] != -1) {
  26.                         printf("%c ->; %c,",per[i],per[j]);   /*i,j are selected*/
  27.                         flag[i][j] = -1;
  28.                         per[i] = per[j] = -1;
  29.                         (j==num-1) ? (n=0):(n=j+1);
  30.                         break;  
  31.                     }      
  32.             }      
  33.         }      
  34.         k++;   
  35.         n=1;   
  36.         resume(per,num);
  37.         printf("\n");
  38.     }
  39. }
复制代码

你对比看看吧

论坛徽章:
0
23 [报告]
发表于 2005-05-10 18:32 |只看该作者

赛程安排的算法

不过,说真的,我不知道第一行的c->;d和第4行的d->;c有什么区别。

论坛徽章:
0
24 [报告]
发表于 2005-05-11 09:09 |只看该作者

赛程安排的算法

[quote]原帖由 "narkissos"]不过,说真的,我不知道第一行的c->;d和第4行的d->;c有什么区别。[/quote 发表:

不知道你看不看球,这是主客场的区别
c->;d,可以认为c是主场而d是客场

论坛徽章:
1
荣誉会员
日期:2011-11-23 16:44:17
25 [报告]
发表于 2005-05-11 10:18 |只看该作者

赛程安排的算法

这个问题好象不是想象中的那么简单
写了一个,只对偶数支队有效(奇数为什么不行,还在研究中。。。),为了简化,只考虑了单循环
  1. #include <stdio.h>;
  2. #include <stdlib.h>;
  3. #define SIZE 100

  4. char flag[SIZE][SIZE];

  5. int getmin(int *node, int num)
  6. {
  7.   int i, min;
  8.   min = 0;
  9.   while(min  < num && node[min] <= 0) min++;
  10.   for(i = min+1; i < num; i++)
  11.     if(node[i] >; 0 && node[i] < node[min]) min = i;
  12.   return min;
  13. }

  14. int getnode(int *node, int num, int i)
  15. {
  16.   int j, min;

  17.   for(min = 0;min < num && (node[min] < 0 || flag[i][min] == -1); min++);
  18.   for(j = min+1; j < num; j++) {
  19.     if(j == i) continue;
  20.     if(node[j] >;= 0 && flag[i][j] != -1 && node[j] < node[min]) min = j;
  21.   }
  22.   if(node[min] < 0) return -1;
  23.   return min;
  24. }

  25. int
  26. main(int argc,char **argv)
  27. {
  28.    int num,i,j,k=0,n,t;
  29.    int  pow[SIZE];
  30.    int  node[SIZE];

  31.    num = atoi(argv[1]);
  32.    for(i = 0; i < num; i++) {
  33.        pow[i] = num - 1;
  34.        for(j = 0; j < num; j++)
  35.            flag[i][j] = 0;
  36.    }
  37.    while(k < num*(num-1)/2/(num/2)) {
  38.      i = 0;
  39.      for(j = 0; j <  num; j++) {
  40.        node[j] = pow[j];
  41.        if(node[j] >; node[i])  i = j;
  42.      }
  43.      for(t = 0; t < num/2; t++) {
  44.        node[i] = -1;
  45.        for(n = 0; n < num; n++) {
  46.          if(node[n] < 0) continue;
  47.          if(flag[i][n] != -1) node[n]--;
  48.        }
  49.        j  = getnode(node, num, i);
  50.        if(j < 0) break;
  51.        node[j] = -1;
  52.        for(n = 0; n < num; n++) {
  53.          if(node[n] < 0) continue;
  54.          if(flag[n][j] != -1) node[n]--;
  55.        }
  56.        flag[i][j] = flag[j][i] = -1;
  57.        printf("%c ->; %c\n",i + 'A', j + 'A');
  58.        pow[i]--;pow[j]--;
  59.        i = getmin(node, num);
  60.      }
  61.      k++;
  62.      printf("\n");
  63.    }
  64. }
复制代码

论坛徽章:
0
26 [报告]
发表于 2005-05-11 10:30 |只看该作者

赛程安排的算法

在给定场地数量后,排出赛程相对容易,但是你的赛程必须保证公平,不能让某支球队连续征战。

论坛徽章:
1
荣誉会员
日期:2011-11-23 16:44:17
27 [报告]
发表于 2005-05-11 10:37 |只看该作者

赛程安排的算法

在偶数支队的情况下,所有的队都在连续征战,奇数支队的时候,每场有一支队轮空
赛程并不好排,我还无法从数学上找到并证明一个可行的办法。。。
我上面的程序在算法上也是错误的。。。

论坛徽章:
0
28 [报告]
发表于 2005-05-11 10:39 |只看该作者

赛程安排的算法

to yuxh:
我把你的代码结果贴在下面了,6支球队的,你只排出了5轮比赛,轮次还不够

  1. sh-2.05b$ ./a.out 6
  2. A ->; B
  3. C ->; D
  4. E ->; F

  5. A ->; C
  6. E ->; B
  7. D ->; F

  8. A ->; D
  9. E ->; C
  10. B ->; F

  11. A ->; E
  12. D ->; B
  13. C ->; F

  14. A ->; F
  15. B ->; C
  16. D ->; E

  17. sh-2.05b$
复制代码

你再看看吧
to JohnBull:
偶数支球队应该不存在你所说的问题,因为每个球队每轮都必须参赛。但现在贴出的代码都还没有解决偶数个球队的情况

论坛徽章:
1
荣誉会员
日期:2011-11-23 16:44:17
29 [报告]
发表于 2005-05-11 10:43 |只看该作者

赛程安排的算法

我是单循环,不是双循环,所以轮数是
num*(num-1)/2/(num/2)
6支队的时候是6*5/2/3=5轮
双循环的话就是10轮,把以上的结果颠倒重复即可

论坛徽章:
0
30 [报告]
发表于 2005-05-11 10:52 |只看该作者

赛程安排的算法

原帖由 "yuxh" 发表:
我是单循环,不是双循环,所以轮数是
num*(num-1)/2/(num/2)
6支队的时候是6*5/2/3=5轮
双循环的话就是10轮,把以上的结果颠倒重复即可

哦,这样的话,我上面贴出的代码也解决了偶数的问题,也可以排出奇数个球队的赛程,但会遇到JohnBull所说的球队连续比赛的问题。5个球队的赛程如下:

  1. !./c3 5
  2. A ->; B
  3. C ->; D

  4. A ->; C
  5. B ->; D

  6. A ->; D
  7. B ->; E

  8. A ->; E
  9. B ->; C

  10. B ->; A
  11. C ->; E
复制代码
您需要登录后才可以回帖 登录 | 注册

本版积分规则 发表回复

  

北京盛拓优讯信息技术有限公司. 版权所有 京ICP备16024965号-6 北京市公安局海淀分局网监中心备案编号:11010802020122 niuxiaotong@pcpop.com 17352615567
未成年举报专区
中国互联网协会会员  联系我们:huangweiwei@itpub.net
感谢所有关心和支持过ChinaUnix的朋友们 转载本站内容请注明原作者名及出处

清除 Cookies - ChinaUnix - Archiver - WAP - TOP