| 网站首页 | 业界新闻 | 小组 | 威客 | 人才 | 下载频道 | 博客 | 代码贴 | 在线编程 | 编程论坛
欢迎加入我们,一同切磋技术
用户名:   
 
密 码:  
共有 2546 人关注过本帖
标题:很急!如何实现对任务项进行随机安排?
只看楼主 加入收藏
taifu945
Rank: 12Rank: 12Rank: 12
等 级:贵宾
威 望:80
帖 子:1545
专家分:3298
注 册:2012-7-6
收藏
得分:0 
楼层表不需要“辅助项”字段,你看我前面给你的代码都没有用到辅助项。固定和随机其实是从人员表里获得信息的,在人员表里指定了各项备注,就是指定了固定听课的地点。你再到楼层表里来一下,不是重复么?再者,如果以后这些标为“固定”的听课地点变成“随机”了呢?再改?看来你还是没有好好看我写的代码,没有领会其中的思路。我在编写分配指定需求人员听课地点的代码中很大一段都是在用人员表的备注信息去查找楼层表的相关地点,你没有看,或者没有看懂。
2016-06-04 22:07
taifu945
Rank: 12Rank: 12Rank: 12
等 级:贵宾
威 望:80
帖 子:1545
专家分:3298
注 册:2012-7-6
收藏
得分:0 
对了,前两天忘记跟你说了,如果你用9.0版本的话,把字符型全改成Varchar吧。你正常数据后面的空格很影响写代码,没看到我用了很多ALLTRIM()函数吗?Varchar型字段可以自动屏蔽掉非用户主动输入的空格。最近可能会有点忙,你先自己试着按新结构修改代码吧,过几天有空了我会再写一份新代码供你参考。


[此贴子已经被作者于2016-6-4 22:32编辑过]

2016-06-04 22:12
dengxsh
Rank: 2
等 级:论坛游民
帖 子:87
专家分:40
注 册:2013-2-26
收藏
得分:0 
回复 22楼 taifu945
谢谢!祝愉快!
2016-06-05 22:00
taifu945
Rank: 12Rank: 12Rank: 12
等 级:贵宾
威 望:80
帖 子:1545
专家分:3298
注 册:2012-7-6
收藏
得分:10 
随机安排(重新设计).rar (7.83 KB)


我把两个表文件结构按前几楼说的要求整理过了,然后重新修改了代码,你有空时研究一下吧。

SET TALK OFF
SET SAFETY OFF
SET COMPATIBLE FOXPLUS
SET DECIMALS TO 15
CLEAR ALL

SELECT 1
USE 领导干部听课安排表 ALIAS 人员表
SELECT 2
USE 教学楼楼层使用状态 ALIAS 楼层表
=RAND(-1)

************************
* 先处理有指定需求的人 *
************************
**************************************************************
* 根据应尽量满足所有条件的原则,按条件数从多到少的顺序整理, *
* 安排人员时,按指定的条件数从多到少顺序逐一进行。           *
**************************************************************
SELECT DISTINCT 人员代码,教学楼备注,VAL(楼层备注) 楼层,节次备注,0 条件数 FROM 人员表 ;
   WHERE !EMPTY(节次备注) OR !EMPTY(教学楼备注) OR !EMPTY(楼层备注) ;
   INTO CURSOR T1 READWRITE

SELECT T1
T1_Fields=AFIELDS(T1_Stru)
SCAN
   条件数量=3 &&初始条件数量都是3个
   FOR AA=2 TO 4
      IF EMPTY(&T1_Stru[AA,1]) THEN &&逐个检查条件
         条件数量=条件数量-1 &&发现空条件就减去一个条件数
      ENDIF
   NEXT
   REPLACE 条件数 WITH 条件数量
ENDSCAN
SELECT * FROM T1 ORDER BY 条件数 DESC INTO ARRAY 指定需求人员

指定需求人员数=ALEN(指定需求人员,1)
FOR AA=1 TO 指定需求人员数
   SELECT 楼层表
   可听课=.T.
   DO CASE

      CASE !EMPTY(指定需求人员[AA,2]) AND 指定需求人员[AA,3]>0 AND !EMPTY(指定需求人员[AA,4]) &&分配情况1:全部都有指定
         LOCATE FOR 教学楼名称==指定需求人员[AA,2] AND VAL(楼层)=指定需求人员[AA,3] AND ;
                    听课节次==指定需求人员[AA,4] AND 使用状态='是'

      CASE !EMPTY(指定需求人员[AA,2]) AND 指定需求人员[AA,3]>0 &&分配情况2:指定教学楼和楼层
         SELECT 听课节次 FROM 楼层表 ;
            WHERE 教学楼名称==指定需求人员[AA,2] AND VAL(楼层)=指定需求人员[AA,3] AND ;
                  使用状态='是' ;
            INTO ARRAY 可用节次
         IF VARTYPE(可用节次)<>'U' THEN &&如果有可听课节次
            IF ALEN(可用节次,1)>1 THEN  &&如果1~4节都可听
               指定需求人员[AA,4]=IIF(INT(RAND()*2+1)=1,'12','34') &&就随机指定两节         
            ELSE
               指定需求人员[AA,4]=可用节次[1,1]
            ENDIF
            LOCATE FOR 教学楼名称==指定需求人员[AA,2] AND VAL(楼层)=指定需求人员[AA,3] AND ;
                       听课节次==指定需求人员[AA,4]
            RELEASE ALL LIKE 可用节次
         ELSE
            可听课=.F.
         ENDIF

      CASE !EMPTY(指定需求人员[AA,2]) AND !EMPTY(指定需求人员[AA,4]) &&分配情况3:指定教学楼和节次
         SELECT 楼层 FROM 楼层表 ;
            WHERE 教学楼名称==指定需求人员[AA,2] AND 听课节次==指定需求人员[AA,4] AND ;
                  使用状态='是' ;
            INTO ARRAY 可用节次
         IF VARTYPE(可用节次)<>'U' THEN &&如果有可听课节次
            可听课地点数=ALEN(可用节次,1)
            IF 可听课地点数>1 THEN  &&如果有多个地点可听
               地点序号=INT(RAND()*可听课地点数+1)
               指定需求人员[AA,3]=VAL(可用节次[地点序号,1]) &&随机指定楼层
            ELSE
               指定需求人员[AA,3]=VAL(可用节次[1,1])
            ENDIF
            LOCATE FOR 教学楼名称==指定需求人员[AA,2] AND VAL(楼层)=指定需求人员[AA,3] AND ;
                       听课节次==指定需求人员[AA,4]
            RELEASE ALL LIKE 可用节次
         ELSE
            可听课=.F.
         ENDIF

      CASE 指定需求人员[AA,3]>0 AND !EMPTY(指定需求人员[AA,4]) &&分配情况4:指定楼层和节次
         SELECT 教学楼名称 FROM 楼层表 ;
            WHERE VAL(楼层)=指定需求人员[AA,3] AND 听课节次==指定需求人员[AA,4] AND ;
                  使用状态='是' ;
            INTO ARRAY 可用节次
         IF VARTYPE(可用节次)<>'U' THEN &&如果有可听课节次
            可听课地点数=ALEN(可用节次,1)
            IF 可听课地点数>1 THEN  &&如果有多个地点可听
               地点序号=INT(RAND()*可听课地点数+1)
               指定需求人员[AA,2]=可用节次[地点序号,1] &&随机指定教学楼
            ELSE
               指定需求人员[AA,2]=可用节次[1,1]
            ENDIF
            LOCATE FOR 教学楼名称==指定需求人员[AA,2] AND VAL(楼层)=指定需求人员[AA,3] AND ;
                       听课节次==指定需求人员[AA,4]
            RELEASE ALL LIKE 可用节次
         ELSE
            可听课=.F.
         ENDIF

      CASE !EMPTY(指定需求人员[AA,2]) &&分配情况5:仅指定教学楼
         SELECT 楼层,听课节次 FROM 楼层表 ;
            WHERE 教学楼名称==指定需求人员[AA,2] AND 使用状态='是' ;
            INTO ARRAY 可用节次
         IF VARTYPE(可用节次)<>'U' THEN &&如果有可听课节次
            可听课地点数=ALEN(可用节次,1)
            IF 可听课地点数>1 THEN  &&如果有多个地点可听
               地点序号=INT(RAND()*可听课地点数+1)
               指定需求人员[AA,3]=VAL(可用节次[地点序号,1]) &&随机指定楼层
               指定需求人员[AA,4]=可用节次[地点序号,2] &&随机指定节次
            ELSE
               指定需求人员[AA,3]=VAL(可用节次[1,1])
               指定需求人员[AA,4]=可用节次[1,2]
            ENDIF
            LOCATE FOR 教学楼名称==指定需求人员[AA,2] AND VAL(楼层)=指定需求人员[AA,3] AND ;
                       听课节次==指定需求人员[AA,4]
            RELEASE ALL LIKE 可用节次
         ELSE
            可听课=.F.
         ENDIF

      CASE 指定需求人员[AA,3]>0 &&分配情况6:仅指定楼层
         SELECT 教学楼名称,听课节次 FROM 楼层表 ;
            WHERE VAL(楼层)=指定需求人员[AA,3] AND 使用状态='是' ;
            INTO ARRAY 可用节次
         IF VARTYPE(可用节次)<>'U' THEN &&如果有可听课节次
            可听课地点数=ALEN(可用节次,1)
            IF 可听课地点数>1 THEN  &&如果有多个地点可听
               地点序号=INT(RAND()*可听课地点数+1)
               指定需求人员[AA,2]=可用节次[地点序号,1] &&随机指定教学楼
               指定需求人员[AA,4]=可用节次[地点序号,2] &&随机指定节次
            ELSE
               指定需求人员[AA,2]=可用节次[1,1]
               指定需求人员[AA,4]=可用节次[1,2]
            ENDIF
            LOCATE FOR 教学楼名称==指定需求人员[AA,2] AND VAL(楼层)=指定需求人员[AA,3] AND ;
                       听课节次==指定需求人员[AA,4]
            RELEASE ALL LIKE 可用节次
         ELSE
            可听课=.F.
         ENDIF

      CASE !EMPTY(指定需求人员[AA,4]) &&分配情况7:仅指定节次
         SELECT 教学楼名称,楼层 FROM 楼层表 ;
            WHERE 听课节次==指定需求人员[AA,4] AND 使用状态='是' ;
            INTO ARRAY 可用节次
         IF VARTYPE(可用节次)<>'U' THEN &&如果有可听课节次
            可听课地点数=ALEN(可用节次,1)
            IF 可听课地点数>1 THEN  &&如果有多个地点可听
               地点序号=INT(RAND()*可听课地点数+1)
               指定需求人员[AA,2]=可用节次[地点序号,1] &&随机指定教学楼
               指定需求人员[AA,3]=VAL(可用节次[地点序号,2]) &&随机指定楼层
            ELSE
               指定需求人员[AA,2]=可用节次[1,1]
               指定需求人员[AA,3]=VAL(可用节次[1,2])
            ENDIF
            LOCATE FOR 教学楼名称==指定需求人员[AA,2] AND VAL(楼层)=指定需求人员[AA,3] AND ;
                       听课节次==指定需求人员[AA,4]
            RELEASE ALL LIKE 可用节次
         ELSE
            可听课=.F.
         ENDIF

   ENDCASE
   IF !FOUND() OR !可听课 THEN &&如果没找到相应教学楼或楼层
      =MESSAGEBOX('没有找到教学楼 '+指定需求人员[AA,2]+' 或楼层 '+STR(指定需求人员[AA,3],2)+CHR(13)+CHR(13);
                  +'无法安排 '+指定需求人员[AA,1]+' 的听课地点。将随机分配...',0,"提醒")
   ELSE
      ***************************************************
      * 如果找到听课地点,先在人员表中填上相应的信息... *
      ***************************************************
      SELECT 人员表
      LOCATE FOR 人员代码==指定需求人员[AA,1]
      REPLACE 教学楼 WITH 楼层表.教学楼名称,楼层 WITH 楼层表.楼层,听课节次 WITH 指定需求人员[AA,4] ;
         FOR 人员代码==指定需求人员[AA,1]
      ****************************************
      * 再在楼层表相应地点的节次状态中“否” *
      ****************************************
      SELECT 楼层表
      REPLACE 使用状态 WITH '否'
   ENDIF
NEXT

************************
* 再处理无指定需求的人 *
************************
SELECT COUNT(DISTINCT 人员代码) 剩余人数 FROM 人员表 WHERE EMPTY(教学楼) INTO ARRAY 剩余人数
SELECT COUNT(楼层) 可听课数 FROM 楼层表 WHERE 使用状态='是' INTO ARRAY 可听课数
IF 剩余人数[1]<可听课数[1] THEN &&如果剩下的人员不够分配
   =MESSAGEBOX('当前可分配听课人员数为 '+STR(剩余人数[1],3)+',可供听课数为 '+STR(可听课数[1],3)+CHR(13)+CHR(13) ;
               +'还缺 '+STR(可听课数[1]-剩余人数[1],3)+' 条任务无法安排。请增加人员...',0,"提醒")
ELSE
   **********************************************
   * 取出可安排听课的无指定需求人员,并随机排列 *
   **********************************************
   SELECT 人员代码,RAND() FROM 人员表 WHERE EMPTY(教学楼) ORDER BY 2 INTO ARRAY 随机人员
   
   ************************
   * 取出可安排听课的楼层 *
   ************************
   SELECT 听课节次,教学楼名称,楼层 FROM 楼层表 WHERE 使用状态='是' INTO ARRAY 可听课楼层
   
   ********************************
   * 开始安排各听课人员对应的楼层 *
   ********************************
   FOR AA=1 TO 剩余人数[1]
      SELECT 人员表
      LOCATE FOR 人员代码==随机人员[AA,1] &&按随机数排好的顺序开始逐个查找定位
      IF AA<=可听课数[1] THEN &&如果可听课数量还没有安排完
         REPLACE 听课节次 WITH 可听课楼层[AA,1],教学楼 WITH 可听课楼层[AA,2],楼层 WITH 可听课楼层[AA,3]
         SELECT 楼层表 &&然后在楼层表中将已分配掉的课程节次注销掉
         LOCATE FOR 教学楼名称==可听课楼层[AA,2] AND VAL(楼层)=VAL(可听课楼层[AA,3]) AND 听课节次==可听课楼层[AA,1]
         REPLACE 使用状态 WITH '否'
      ELSE
         EXIT
      ENDIF
   NEXT

ENDIF

SET TALK ON
SET SAFETY ON
SET DECIMALS TO 2
USE IN T1
RETURN


[此贴子已经被作者于2016-6-7 11:06编辑过]

2016-06-07 10:51
dengxsh
Rank: 2
等 级:论坛游民
帖 子:87
专家分:40
注 册:2013-2-26
收藏
得分:0 
回复 24楼 taifu945
谢谢老师!
每执行一次程序,都将依次把“教学楼楼层使用状态.DBF”中“使用状态”为“是”的改成“否”,目的是为了便于查看还有哪几层没有被安排!
——————————————
若要重新得到分配方案,就必须进行如下操作:
1.利用“BLANK FIELDS 教学楼,楼层,听课节次 all”语句,对“领导干部听课安排表.DBF”中教学楼、楼层、听课节次字段进行数据清空。
2.重新拷贝“教学楼楼层使用状态(原始数据).DBF”表,并将表名更改为“教学楼楼层使用状态”(与程序中的名称一致)。
3.运行“随机安排听课人员.prg”程序。

请教,能否不改写楼层的使用状态?
2016-06-07 12:26
dengxsh
Rank: 2
等 级:论坛游民
帖 子:87
专家分:40
注 册:2013-2-26
收藏
得分:0 
回复 24楼 taifu945
另外,能否直接将分配好的数据表导出成excel,路径为该文件夹更目录,文件名为“分配方案”
2016-06-07 13:21
dengxsh
Rank: 2
等 级:论坛游民
帖 子:87
专家分:40
注 册:2013-2-26
收藏
得分:0 
回复 26楼 dengxsh
保存excel已解决:
USE 领导干部听课安排表
COPY TO ".\分配方案.XLS" TYPE XLS
——————————
还是之前的问题:能否不改写楼层的使用状态?
2016-06-07 14:24
taifu945
Rank: 12Rank: 12Rank: 12
等 级:贵宾
威 望:80
帖 子:1545
专家分:3298
注 册:2012-7-6
收藏
得分:0 
实际上,楼层表的“使用状态”字段就是一个听课地点是否已被分配掉的标志。除了对教学楼、楼层、节次同时有限制的人以外,其他所有人都是有一定随机性的,只不过需求条件多的随机性相对局限些;需求条件少的,乃至没有任何条件的,随机性就大些。随机分配哪些听课地点,其实“使用状态”字段里的标记是一个很重要的参考数据。如果你仔细研究过我的代码,想必也会发现几乎所有的SELECT-SQL命令中都带有“使用状态='是'”的WHERE条件。那么你再想象一下,如果该字段不作改变,程序随机安排时就有很大可能出现问题:即,前面已被分配掉的地点又被分配到另一个人身上去了。
不知道这段解释你是否看得懂?编写程序代码逻辑思维和算法都很重要,要通盘考虑,不能写到哪算哪。
2016-06-07 15:28
快速回复:很急!如何实现对任务项进行随机安排?
数据加载中...
 
   



关于我们 | 广告合作 | 编程中国 | 清除Cookies | TOP | 手机版

编程中国 版权所有,并保留所有权利。
Powered by Discuz, Processed in 0.020788 second(s), 10 queries.
Copyright©2004-2024, BCCN.NET, All Rights Reserved