我使这里成为谁拥有一类的21名学生同事。他需要在一年中将他们分成3个小组,但每个小组永远都不能有一个成员与另一个成员在一起。
我已经写程序,这使我25组的输出。但是我不知道这是最多的团体,似乎太少了。
我该如何去到下一行的foreach当学生已经与学生之前进行测试。歇停止整个循环中,继续被标记为多余的。我可以有2人组的第一个已经与一个被检查的,但第二个有没有,所以布尔被复位为假。
else //they have met that person before
{
IsStudentBeen = true;
}
有人可以请检查,如果我的代码是正确的?
private void BtnCalc_Click(object sender, EventArgs e)
{
//need to have a list of all students to record all students they have been in a group with
//output to date = 25 groups
//All students have a list that contains all the students they have been in a group with before.
List<string>[] StudentHistory = new List<string>[22];
//Instantiate the lists = names
for (int i = 1; i < 22; i++)
{
StudentHistory[i] = new List<string>();
}
List<string> singlegroup = new List<string>();
for (int k = 1; k < 21; k++) //get all permutations
{
for (int i = k; i < 22; i++)
{
string student = i.ToString();
string StudentToAdd = null;
//Need to add the first memebr manually or it crashes at the foreach
if (singlegroup.Count == 0)
{
singlegroup.Add(student);
StudentHistory[1].Add(student);
}
else
{
bool IsStudentBeen = false;
foreach (var AGroupStudent in singlegroup) // for each person in the group
{ //convert the person to an int to find their history list
int GroupStudent = Convert.ToInt32(AGroupStudent);
if (!StudentHistory[GroupStudent].Contains(student))
{
//if the student isn't in the group, and they have never been with the others then add them
if (IsStudentBeen == false)
{
StudentToAdd = student;
}
//add that person to the history of the others
StudentHistory[GroupStudent].Add(student);
}
else //they have met that person before
{
IsStudentBeen = true;
}
}
//add the student to the group
if (IsStudentBeen == false)
{
singlegroup.Add(StudentToAdd);
}
//if the group has reached 3 then print it and clear it for the next group
if (singlegroup.Count == 3)
{
String Group = null;
foreach (var item in singlegroup)
{
Group += item + " ";
}
lbxOutput.Items.Add(Group);
singlegroup.Clear(); //empty the list ready for the next one
}
}
}
// count++;
// this.Text = count.ToString();
// }
}
}
答案 0 :(得分:1)
另一个SO参与者贡献大致如下的答案:
var students = Enumerable.Range(1, 21).ToArray();
var groups = new List<int[]>();
foreach(var s1 in students)
foreach(var s2 in students.Where(s => s > s1))
foreach(var s3 in students.Where(s => s > s2))
{
int[] a = { s1, s2, s3 };
bool allowed = true;
foreach(var g in groups)
{
if (g.Contains(s1) && (g.Contains(s2) || g.Contains(s3)) ||
g.Contains(s2) && g.Contains(s3))
{
allowed = false;
break;
}
}
if (allowed)
{
groups.Add(a);
}
}
Console.WriteLine($"groups: {groups.Count}");
这个答案对我来说是有意义的,但已被原始作者删除。
它找到50
个学生组,每个3
个学生,其中没有任何一个组共享同一对学生。
替代答案:
(在有些不同的假设下)
有7支球队,每轮3名学生。下一轮,没有学生可以组队,与他/她以前的2r
团队成员,如果r
是轮数为止。因此,不可能进行25发回合。对于21名学生,最大回合数必须小于10。
以下代码找到了6个回合:
1: 1 2 3 | 4 5 6 | 7 8 9 | 10 11 12 | 13 14 15 | 16 17 18 | 19 20 21
2: 8 12 21 | 20 17 7 | 2 11 15 | 1 16 10 | 4 9 19 | 13 3 5 | 18 6 14
3: 20 2 18 | 5 12 14 | 8 16 4 | 10 7 21 | 6 1 19 | 3 15 17 | 11 13 9
4: 12 9 2 | 5 8 11 | 1 13 17 | 19 10 18 | 3 20 16 | 4 14 7 | 21 6 15
5: 7 19 5 | 14 1 8 | 15 12 20 | 21 16 11 | 17 10 4 | 18 3 9 | 13 2 6
6: 18 8 15 | 13 12 7 | 2 10 5 | 6 11 17 | 19 16 14 | 20 1 9 | 4 21 3
class Program
{
static Random random = new Random();
static int students = 21;
static int studentsPerGroup = 3;
static int groups = students / studentsPerGroup;
static List<int[]> history = new List<int[]>();
static void Main(string[] args)
{
int[] order = Enumerable.Range(1, students).ToArray();
int round = 1;
history.Add(order);
showOrder(round, order);
while (++round < 500)
{
do
{
order = shuffle(ref order);
}
while (!allowed(ref order));
history.Add(order);
showOrder(round, order);
}
Console.WriteLine("ciao!");
}
private static bool allowed(ref int[] order)
{
for (int g = 0; g < groups; g++)
for (int i = 0; i < studentsPerGroup - 1; i++)
for (int j = i + 1; j < studentsPerGroup; j++)
{
int student1 = order[g * studentsPerGroup + i];
int student2 = order[g * studentsPerGroup + j];
foreach (var ord in history)
{
int g1 = 0;
int g2 = 0;
for (int k = 0; k < students; k++)
if (ord[k] == student1)
{
g1 = k / studentsPerGroup;
break;
}
for (int k = 0; k < students; k++)
if (ord[k] == student2)
{
g2 = k / studentsPerGroup;
break;
}
if (g1 == g2)
{
return false;
}
}
}
return true;
}
static void showOrder(int n, int[] order)
{
string s = string.Format("{0,4}:", n);
int i = 0;
foreach(var st in order)
{
s += string.Format(" {0,2}", st);
if (++i % studentsPerGroup == 0)
{
s += " |";
}
}
Console.WriteLine(s);
}
static int[] shuffle(ref int[] arr)
{
return arr.OrderBy(i => random.Next()).ToArray();
}
}
我无法分析21名学生的所有21! = 5.1e19
排列。因此,我求助于随机洗牌。