排班算法,很现实,哪个单位都会用得着,高手相送5000分

lizhongkun 2009-03-03 03:35:55
a1,a2,a3,a4,a5
b1,b2,b3,b4,b5,
c1,c2,....
...
==>
编排成每天四人一组:a1,b1,c1,d1
如果a1,c3,不在则
==>a2,b1,c1,d1
a3,b2,c2,d2
a4,b3,c4,d3
a5,b4,c5,d4
回来后进入队列等待排班就行,不用优先
明白不,
a,b,c,d,e,f,g,h依次顺序有八个处,
每个处有3-12人不等
处内循环
工作日周一至五排一班,
要记录上周各处排到的最后一个人a4,b5,c8,d6..及周五第4个人所在处室a,本周先确定在位人员后接着轮换b6,c9,d7...
...全文
3527 119 打赏 收藏 转发到动态 举报
AI 作业
写回复
用AI写文章
119 条回复
切换为时间正序
请发表友善的回复…
发表回复
wlcsdf 2012-03-21
  • 打赏
  • 举报
回复
[Quote=引用 51 楼 zming 的回复:]
谈谈我的思路:

1. 同部门的人排序号,从1开始

a1, a2, a3, a4
b1, b2, b3, b4, b5
c1, c2, c3, c4
d1, d2, d3

2. 每部门抽出序号最小的一个,同时,该人的序号重置为本部门 最大序号+1

则 a1 --> a5
b1 --> b6
c1 --> c5
d1 --> d4

3. 回到第二步……
[/Quote]

这个思路的问题在于:

一、如果用序号字段排先后,那么在循环时依靠什么字段呢?比如
select * from db order by 序号

序号同时作为排序依据,又在不断变化,容易出错。

二、如果用数据表自动生成的ID作为排序依据,比如
select * from db order by ID

那么排每天的班都要把数据表从头到尾检索一遍,因为根据人员出差或请假,排班顺序是会变化的。
wlcsdf 2012-03-21
  • 打赏
  • 举报
回复
错错错错错。

我提一个意见。这个排班有个问题。
假设有五个人排班,A,B,C,D,E。如果C出差工作,回来时很辛苦,大家照顾他,说其他四个人值四天班,你再接上吧。比如当天是D值班,那么C就等四天后再值班,排班顺序变成D,C,A,B,E。
这种情况怎么解决?
难点一,如果在循环过程中改变循环顺序,会引发循环紊乱。
难点二,如果再建一个排班表,将新的排班顺序拷贝过去,利用新表循环,也会因指针丢失而与原循环人员衔接不上。
熙风 2012-03-21
  • 打赏
  • 举报
回复
我关心的楼主有么有5K分
山东蓝鸟贵薪 2012-03-21
  • 打赏
  • 举报
回复
顶顶帖子
关注一下
PaulyJiang 2012-03-21
  • 打赏
  • 举报
回复
队列,先进先出就OK了
有那么烦么?
tangxu12 2012-03-21
  • 打赏
  • 举报
回复
我还没有你分高呢!
文少 2012-03-21
  • 打赏
  • 举报
回复
int p_num = 5;//人数
System.Collections.ArrayList a = new System.Collections.ArrayList(p_num);//人数
System.Collections.ArrayList b = new System.Collections.ArrayList(p_num);
System.Collections.ArrayList c = new System.Collections.ArrayList(p_num);
System.Collections.ArrayList d = new System.Collections.ArrayList(p_num);
string banzu;//
for (int i = 0; i < 30; i++)//天
{

banzu = a[i % a.Count].ToString();
banzu = banzu + b[i % b.Count].ToString();
banzu = banzu + c[i % c.Count].ToString();
banzu = banzu + d[i % d.Count].ToString();
}
luqing200862 2011-05-12
  • 打赏
  • 举报
回复
上班时间,不多言,回头讨论~~~~~~~
pls53 2011-05-12
  • 打赏
  • 举报
回复
留个排班的demo,邮箱546617075@qq.com
iGouzy 2009-03-10
  • 打赏
  • 举报
回复
这种结构可以解决你上面的问题,其实问题比较简单,你可以假设全年的假日是连在一起的,那么,按照正常班去排吧~~然后人少的问题,如果一个组轮完可以转到其它组的话就好实现了,比如 c 有两个人, 通常情况下应该是 a1,b1,c1,d1, c 轮完的情况下可以变成 a3,b3,e1,d3 这样的话就好解决了。

PS:现在楼主的问题已经脱离技术问题上升到运筹了,属于业务的范畴了~~这一部分最好由了解业务的朋友回答一下

[Quote=引用 94 楼 phoenix8343_cn 的回复:]
再补一部分(实现部门更换),PS:不好意思啊,要工作还要照顾一下股票,所以回帖比较慢,见谅

C# codepublic class Item
{
public string Name = string.Empty; //名称
public Item Next = null; //下一个
public int Count = default(int); //值班次数
public bool Tag = false; //在某一轮是否已经值过班

public Item() { }

public Item(string name) : th…
[/Quote]
iGouzy 2009-03-09
  • 打赏
  • 举报
回复
mark 一下,晚上回
wuyi8808 2009-03-08
  • 打赏
  • 举报
回复
up
lizhongkun 2009-03-08
  • 打赏
  • 举报
回复
a1,a2,a3,a4,a5,a6
b1,b2,b3,b4
c1,c2
d1,d2,d3,d4
e1,e2,e3,e4,e5
f1,f2,f3,f4
g1,g2
h1,h2,h3,h4,h5,h6,h7
上次元旦3天
坐班:a1,b2,c1
值班:a2,b1,c2
d1,e1,f1
g1,h1,a3
这次春节7天:
坐班:现d,e,f,g,h,a,b记录的坐班顺序是d1,e1,f1,g1,h1,a2,b3,c2 //如果要公平,这几个应该都休息,而应该是先轮元旦休息的
值班:b2,d2,e2//上次最后那天最后一个人到a,这次从b开始,b上次是b1,这次应该是b2,但是b2这次已经坐班了,所以是b3,c处人少,不轮了
f2,g2,h2
a4,b4,c1
d3,e3,f3
h3,a5,d4//g处人少,不轮了,b都论完的情况下,还有d,e,h处的人一次没轮过,优先轮他们
e4,f4,h4
a6,e5,h5//c,g处人少,不轮了;bd都论完的情况下,还有e,h处的人一次没轮过,优先轮他们

是不是很麻烦,呵呵,
谢谢,
我会开50个贴子让大家来领分,那个把两个算法都弄好,就先给2000分,不忙的可以好好争取一下哦
lizhongkun 2009-03-08
  • 打赏
  • 举报
回复
[Quote=引用 103 楼 phoenix8343_cn 的回复:]
后面的规则不太明白,楼主能多说一点吗?
关于人少的部门轮的次数比较多的情况,如果要解决的话,可以变更现有的排班制度吗?如果不能更改的话,是否允许abcd或者efgh中内部进行调整?
[/Quote]

比如C处只有2个人,其他处有的有10个,有的有8,7,5,4,等不等,并且每周人数也不固定,
要实现公平,真的很难,
我现在用的办法是人少的处就三周再轮一次,

我现在的难点是实现公平!
节日值班稍微复杂点,每天值班三个人,......
类似该贴题目规则,
节日增加了坐班(24小时坐着,呵呵),不过坐班简单,每天一个处确定一个人就行,不用实现这个了
要记录上次节日该处哪些人安排了值班和坐班,
这次节日轮到该处则尽量不安排那些人,
现实中现只有手工记录两套顺序,该处坐班人员顺序和该处节日值班人员顺序,所以导致某个节日某个人既值班又坐班,这是个矛盾.
节日值班比平时工作日值班更辛苦,所以必须要考虑公平问题,
如果按照abcdefgh顺序轮换处,人少的处要轮的也一样多,则人少的处的就不能过节了!一个节日比如春节某个人甚至会值几次还有坐班!呵呵
例如:

a1,a2,a3,a4,a5,a6
b1,b2,b3,b4
c1,c2
d1,d2,d3,d4
e1,e2,e3,e4,e5
f1,f2,f3,f4
g1,g2
h1,h2,h3,h4,h5,h6,h7
上次元旦3天
坐班:a1,b2,c1
值班:a2,b1,c2
d1,e1,f1
g1,h1,a3
这次春节7天:
坐班:现d,e,f,g,h,a,b记录的坐班顺序是d1,e1,f1,g1,h1,a2,b2,c2 //如果要公平,这几个应该都休息,而应该是先轮元旦休息的
值班:b3,d2,e2//上次最后那天最后一个人到a,这次从b开始,b上次是b1,这次应该是b2,但是b2这次已经坐班了,所以是b3,c处人少,不轮了
f2,g2,h2
a4,b4,c1
d3,e3,f3
h3,a5,d4//g处人少,不轮了,b都论完的情况下,还有d,e,h处的人一次没轮过,优先轮他们
e4,f4,h4
a6,e5,h5//c,g处人少,不轮了;bd都论完的情况下,还有e,h处的人一次没轮过,优先轮他们

是不是很麻烦,呵呵,
谢谢,
我会开50个贴子让大家来领分,那个把两个算法都弄好,就先给2000分,不忙的可以好好争取一下哦
iGouzy 2009-03-06
  • 打赏
  • 举报
回复
后面的规则不太明白,楼主能多说一点吗?
关于人少的部门轮的次数比较多的情况,如果要解决的话,可以变更现有的排班制度吗?如果不能更改的话,是否允许abcd或者efgh中内部进行调整?
lizhongkun 2009-03-06
  • 打赏
  • 举报
回复
要认真学习,谦虚谨慎,呵呵 ,集思广益嘛,
lizhongkun 2009-03-06
  • 打赏
  • 举报
回复
啥时候继续??
yas 2009-03-06
  • 打赏
  • 举报
回复
受不了了,有那么难吗?有5000分的人,自己搞不ding?
胖叮 2009-03-06
  • 打赏
  • 举报
回复
虽然我做的人力资源系统不是这样排班的,学习下!
iGouzy 2009-03-05
  • 打赏
  • 举报
回复
再补一部分(实现部门更换),PS:不好意思啊,要工作还要照顾一下股票,所以回帖比较慢,见谅
public class Item
{
public string Name = string.Empty; //名称
public Item Next = null; //下一个
public int Count = default(int); //值班次数
public bool Tag = false; //在某一轮是否已经值过班

public Item() { }

public Item(string name) : this()
{ this.Name = name; }

public Item(string name, Item next) :this(name)
{ this.Next = next; }
}

public class Link
{
public event EventHandler LoopEnded = null; //当全部成员执行结束以后触发

private Item Head = null; //第一个成员
public string Name = string.Empty; //部门名称
public bool Tag = false; //某次部门循环结束

private bool CheckLoopEnded() //某次检查循环是否结束
{
if (Head == null) return true;

Item current = Head;
bool result = true;

while (result && current != null)
{
result &= current.Tag;
current = current.Next;
}

return result;
}

private void ClearTags()
{
Item current = Head;

while (current != null)
{
current.Tag = false;
current = current.Next;
}
}

public void Remove(string name) //某人请假
{
if (Head == null) return;

if (Head.Name == name) { Head = Head.Next; return; }

Item current = Head;

while (current.Next != null)
{
if (current.Next.Name == name)
current.Next = current.Next.Next;

current = current.Next;
}
}

public void Add(string name) //某人加入(请假回来)
{
Add(new Item(name));
}

public void Add(Item item) //某人加入(请假回来)
{
if (Head == null) { Head = item; return; }

Item current = Head;

while (current.Next != null) current = current.Next;

item.Next = null;
current.Next = item;
}

public void MoveNext() //循环一轮
{
if (Head == null || Head.Next == null) return;

Item result = Head;

Head = Head.Next;

result.Count++;
result.Tag = true;

Add(result);

if (CheckLoopEnded())
{
ClearTags();
if (LoopEnded != null) LoopEnded(this, null);
}
}

public void Debug()
{
Item current = Head;

while (current != null)
{
System.Diagnostics.Debug.Write(string.Format("{0}[{1}]\t", current.Name, current.Count));

current = current.Next;
}

System.Diagnostics.Debug.WriteLine(string.Empty);
}
}

public class Puzzle
{
Link[] links = null;
private string[][] _data = null;

public string[][] Data
{
get { return _data; }
set {
_data = value;
}
}

private void InitialLinks()
{
int i = default(int);

links = new Link[_data.GetLength(0)];

for (int j = 0; j < links.Length; j++)
{
links[j] = new Link();
links[j].LoopEnded += new EventHandler(Puzzle_TurnEnd);
}

foreach (string[] ret in _data)
{
Link l = links[i++];

foreach (string r in ret) l.Add(r);
}
}

private void Puzzle_TurnEnd(object sender, EventArgs e)
{
Link l = (sender as Link);

l.Tag = true;
}

public string[][] GetSchedule(int count, int department_count)
{
InitialLinks();

int k = 0;

for (int i = 1; i <= count; i++)
{
if (i == 2)
{
links[0].Remove("d2");//d2在第二天请假
}
else if (i == 4)
{
links[0].Add("d2");//d2在第4天请假回来
}

bool result = true;

for (int j = k; j < k + department_count; j++)
{
if (j >= links.Length) break;

Link l = links[j];

l.MoveNext();
l.Debug();

result &= l.Tag;
}

if (result)
{
System.Diagnostics.Debug.WriteLine("Turn End");
for (int j = k; j < k + department_count; j++)
{
if (j >= links.Length) break;

links[j].Tag = false;
}

if (k + department_count >= links.Length) k = 0;
else k += department_count;

}

System.Diagnostics.Debug.WriteLine(string.Empty);

}

return _data;
}
}
加载更多回复(97)

111,094

社区成员

发帖
与我相关
我的任务
社区描述
.NET技术 C#
社区管理员
  • C#
  • AIGC Browser
  • by_封爱
加入社区
  • 近7日
  • 近30日
  • 至今
社区公告

让您成为最强悍的C#开发者

试试用AI创作助手写篇文章吧