【转】24位老人分三桌就餐有关问题(200分)
【转】24位老人分三桌就餐问题(200分)
退休那年,看到赵慈庚在 <数学通报> 提出一个未曾解决的问题:有24位老人,从76岁到99岁,每岁一人,他们分三桌就餐,每桌8人,要求各桌年龄的和相等,问有多少种分桌法?
当时我考虑过,试图解决,可是两次都失败了。后来再未考虑。今翻看旧日笔记,又想碰碰它,仍未能解决,现在提出来,希望大家来帮助。
【注】这个问题应属于算法问题,但现在在《专题开发》板块中已找不到《算法和数据结构》小块了,所以我只得将问题放在这里,因为原来《算法和数据结构》是和《图形图像》合在一起的,或许很多老手还忘不了这里...
------解决方案--------------------
分成12对,保证每对的年龄都等于平均年龄乘以2,即:(76,99)(77,98)(78,97)(79,96),只要保证每一对在同一桌,就可以达到题目要求,也就成了一个排列组合。
但这只是得到一部分解
------解决方案--------------------
找出8个和为700的组合,剩余的16个里面找出8个和为700的组合
然后总的除以3
未解决不至于吧,最多效率慢点。
------解决方案--------------------
Result: 1025113
Elapsed time 0.218
几分钟迅速写了一个小程序。
------解决方案--------------------
看你怎么定义同类问题了。大框架搜索类型的题碰到过很多。具体有没有和这道题类似的话那就不记得了。
------解决方案--------------------
才24个人,还有这么多限制,暴力绝对能搞。
------解决方案--------------------
楼主要的是数学公式。
可惜,组合数学的公式往往比较复杂,况且这里也不方便对公式排版。
------解决方案--------------------
5#能讲讲思路么
------解决方案--------------------
既然写了还是贴出来吧,就当备份代码了。
------解决方案--------------------
退休那年,看到赵慈庚在 <数学通报> 提出一个未曾解决的问题:有24位老人,从76岁到99岁,每岁一人,他们分三桌就餐,每桌8人,要求各桌年龄的和相等,问有多少种分桌法?
当时我考虑过,试图解决,可是两次都失败了。后来再未考虑。今翻看旧日笔记,又想碰碰它,仍未能解决,现在提出来,希望大家来帮助。
【注】这个问题应属于算法问题,但现在在《专题开发》板块中已找不到《算法和数据结构》小块了,所以我只得将问题放在这里,因为原来《算法和数据结构》是和《图形图像》合在一起的,或许很多老手还忘不了这里...
------解决方案--------------------
分成12对,保证每对的年龄都等于平均年龄乘以2,即:(76,99)(77,98)(78,97)(79,96),只要保证每一对在同一桌,就可以达到题目要求,也就成了一个排列组合。
但这只是得到一部分解
------解决方案--------------------
找出8个和为700的组合,剩余的16个里面找出8个和为700的组合
然后总的除以3
未解决不至于吧,最多效率慢点。
------解决方案--------------------
#include <iostream>
#include <ctime>
using namespace std;
const int MaxN = 24;
const int MaxM = 3;
int assign[MaxN], cursum[MaxM], curcount[MaxM], target;
int result;
void DFS(int i, int maxassigned)
{
if(i < 0)
{
++result;
return;
}
for(int j=0;j<=maxassigned+1 && j < MaxM;j++)
{
if(cursum[j] + i > target)
continue;
if(curcount[j] + 1 > MaxN / MaxM)
continue;
assign[i] = j;
cursum[j] += i;
++curcount[j];
DFS(i-1, j>maxassigned ? j : maxassigned);
cursum[j] -= i;
--curcount[j];
}
}
int main()
{
target = MaxN * (MaxN-1) / 2 / MaxM;
DFS(MaxN-1, -1);
cout<<"Result: "<<result<<endl;
cout<<"Elapsed time "<<(double)clock()/CLOCKS_PER_SEC<<endl;
return 0;
}
Result: 1025113
Elapsed time 0.218
几分钟迅速写了一个小程序。
------解决方案--------------------
看你怎么定义同类问题了。大框架搜索类型的题碰到过很多。具体有没有和这道题类似的话那就不记得了。
------解决方案--------------------
才24个人,还有这么多限制,暴力绝对能搞。
------解决方案--------------------
楼主要的是数学公式。
可惜,组合数学的公式往往比较复杂,况且这里也不方便对公式排版。
------解决方案--------------------
5#能讲讲思路么
------解决方案--------------------
既然写了还是贴出来吧,就当备份代码了。
using System;
public class Test
{
static int[] Counter = new int[3];
static int[] Sum = new int[3];
static int Result = 0;
static int CountValue = 8, SumValue = 100;
static void Dfs(int num, int max)
{
if (num == 0)
Result++;
else
{
for (int i = 0; i <= max; i++)
{
if (Counter[i] >= CountValue
------解决方案--------------------
Sum[i] + num > SumValue)
continue;
if (Counter[i] + 1 == CountValue && Sum[i] + num != SumValue)
continue;
int maxNext = max < 2 && max == i ? i + 1 : max;
Counter[i]++; Sum[i] += num;
Dfs(num - 1, maxNext);
Sum[i] -= num; Counter[i]--;
}
}
}
static void Main()
{
DateTime begin = DateTime.Now;
Dfs(24, 0);
Console.WriteLine(Result);
Console.WriteLine(DateTime.Now - begin);
}
}
------解决方案--------------------