和尚值日问题!大家看看有没有更好办法

Dinelgua 2009-04-14 11:05:36
问题 有7个和尚,每人可以值一周中的两天,请输出一周所有可能值日表,如 和尚甲可以值 周二 周四 乙可以值 周三周日

...全文
157 19 打赏 收藏 转发到动态 举报
写回复
用AI写文章
19 条回复
切换为时间正序
请发表友善的回复…
发表回复
Dinelgua 2009-04-17
  • 打赏
  • 举报
回复
顶上
Dinelgua 2009-04-14
  • 打赏
  • 举报
回复
一个和尚一周内必须值一天,至少值一天


和尚甲可以值 周二 周四

那么方案中 要么他再周二值日 要么再周四值日 不能同时值二和四 但 至少值一天
Dinelgua 2009-04-14
  • 打赏
  • 举报
回复
问题确认:

一天只能有一个和尚值日
一个和尚一周只能值一天
liliangbao 2009-04-14
  • 打赏
  • 举报
回复
帮顶~
ryuk33 2009-04-14
  • 打赏
  • 举报
回复
请说清楚问题:

1> 一天是否只要一个和尚值日?
2> 和尚是否可以值日“0天”,“1天”,“2天”?
xu54647265 2009-04-14
  • 打赏
  • 举报
回复
请问,是一个和尚可以值2天,但是只能在2天中选一天吗?还是可以一个人值2天,有人可以一个周内不用值日?
Dinelgua 2009-04-14
  • 打赏
  • 举报
回复
已有方法如下,看看没有问题 或更好方法


#include <iostream>
using namespace std;
//有7个和尚,每人可以值一周中的两天,请输出一周所有可能值日表
//七个和尚(MONK)可以值日情况
int Monk[7][2] =
{
{1,2},//和尚1
{2,1},//和尚2
{4,3},//和尚3
{5,4},//和尚4
{3,7},//和尚5
{1,6},//和尚6
{7,5} //和尚7

};
int iSolutionNum = 0;
int WeekStat[7]; //标识每天安排值日的情况 true为已安排,false为未安排
void print();
int Schedule(int iCurMonk,int iWeekDate)
{
if (iCurMonk == 7)//iCurMonk从0到6为有效值,到7说明已全部安排完毕 -- 成功
{
iSolutionNum++;
print();
return 1;
}
else if (0 != WeekStat[iWeekDate-1])//iWeekDate取值范围是1-7,数组中对应星期是0-6所以减1
{
return 0;
}
else
{
if(-1 != iCurMonk)//第一次运行
{
WeekStat[iWeekDate-1] = iCurMonk+1;//iWeekDate取值范围是1-7,数组中对应星期是0-6所以减1
}

//因为一共就7个和尚,对应7天 所以每个和尚都必然被选择到
//不必像背包问题那样回溯,只要将每个和尚可以值的两天日回溯了就行
if (6 == iCurMonk)//已经递归到头了不需要再看第
{
Schedule(7,0);
}
else
{
Schedule(iCurMonk+1,Monk[iCurMonk+1][0]);//看和尚的可以值的第一个日是否可以分配
Schedule(iCurMonk+1,Monk[iCurMonk+1][1]);//看和尚的可以值的第二个日是否可以分配
}

WeekStat[iWeekDate-1] = 0;//递归每回退一层就将本层设置的值日状态清空
return 0;
}
}
void main()
{
Schedule(-1,0);
cout << "共有 " << iSolutionNum << " 种解决方案" <<endl;

}
void print()
{
cout << "解决方案\n";
for (int i =0; i<7; i++)
{
if (i != 6)
{
cout << WeekStat[i];
}
else
{
cout << WeekStat[i] << endl;
}
}
}
Dinelgua 2009-04-14
  • 打赏
  • 举报
回复
啥作业呀 哥们儿早毕业了
你没看我自己的写完了么 上面贴的就是

兄弟分析这么多 写出代码来 一起研究研究
我的代码在1楼
ryuk33 2009-04-14
  • 打赏
  • 举报
回复
[Quote=引用 15 楼 Dinelgua 的回复:]
ls兄弟分析的不错
写个代码贴出来 学习下
[/Quote]

:)
这应该是你的作业之类的吧?还是你自己写吧。给你锻炼的机会。呵呵。


如果你已经写完了,贴出来,我倒是可以帮你改改。或者写一个我自己的。
但是得看到你自己的代码先。
ryuk33 2009-04-14
  • 打赏
  • 举报
回复
算法复杂度为:O(2n)

注:实现时,事先建立一个数组,每个元素,对应当天的可能和尚。如此,可以把O(n)的查找(查找该天,还有哪些和尚),降低到O(1)。

遍历两次:造数组一次,算循环一次。


所以复杂度是O(2n)
Dinelgua 2009-04-14
  • 打赏
  • 举报
回复
ls兄弟分析的不错
写个代码贴出来 学习下
ryuk33 2009-04-14
  • 打赏
  • 举报
回复
循环数的计算:

{1,2},//和尚1
{2,1},//和尚2
{4,3},//和尚3
{5,4},//和尚4
{3,7},//和尚5
{1,6},//和尚6
{7,5} //和尚7

首先,随便拿一个和尚,假如是和尚6:
和尚6可能的天数为: {1, 6}

那么,看一下,包含1的和尚有: 和尚1,和尚2。
包含6的和尚有: 无

所以,和尚6无法组成循环。和尚6退出。


然后,下一个和尚,假如是和尚1:
和尚1可能的天数为: {1, 2}

那么,看一下,包含1的和尚有: 和尚2,和尚6(已经被排除)。
包含2的和尚有: 和尚2。

得到:和尚1与和尚2组成循环,循环数+1。 和尚1,2退出。


接着,下一个和尚,假如是和尚3,
和尚3可能的天数为: {3, 4}

那么,看一下,包含3的和尚有: 和尚5。
包含4的和尚有: 和尚4。

随便挑一个,假如是挑了和尚5,那么,和尚5,除了第3天以外,还包含的,是第7天
继续,包含第7天的,还有 {7,5} //和尚7 。
继续,包含第5天的,还有 {5,4},//和尚4
继续,和尚4的另一天,就是第4天,又是一个循环. 循环数+1。 和尚3,5,7,4退出。

没有剩余的和尚,退出。

答案:2 ^ 2 = 4;

ryuk33 2009-04-14
  • 打赏
  • 举报
回复
周6:只能是和尚6

乘以

周一:和尚1
周二:和尚2



周一:和尚2
周二:和尚1

这两种可能,乘以

周3:和尚3
周4:和尚4
周5:和尚7
周日:和尚5




周3:和尚5
周日:和尚7
周5:和尚4
周4:和尚3

这两种可能。

Dinelgua 2009-04-14
  • 打赏
  • 举报
回复
感谢ls 兄弟意见
请大家继续讨论 共同进步
ryuk33 2009-04-14
  • 打赏
  • 举报
回复
搞定了,我终于想出来了,O(1)的算法,哈哈!!


可能的组合数为:

2 ^ (循环数), 即,有多少循环,组合数,就是2的多少次方。

如果没有循环,就只有1种可能。
如果有1个循环,就有2种可能。
3个循环,就是8种可能。(上限是3个循环)。



举楼主的例子吧:
{1,2},//和尚1
{2,1},//和尚2
{4,3},//和尚3
{5,4},//和尚4
{3,7},//和尚5
{1,6},//和尚6
{7,5} //和尚7


{1,2},{2,1} : 1个循环
{4,5}, {5,7}, {7,3}, {3,4}: 1个循环
{1,6}: 没有循环


所以,这个例子的解就是: 2 ^ 2 = 4种可能。分别是:
ryuk33 2009-04-14
  • 打赏
  • 举报
回复
最坏的情况,是"2,2,2,2,2,2,2",就是每一天都有可能的两个和尚。这时的计算就比较慢一点。

但,假如有任何一天,可能的和尚数 >= 3,那么,就至少有一天,可能的和尚数为1。

由于这一天只有一个和尚可以值日,而每一天又都必须要有和尚值日,所以,这一天由这一个和尚来值日,就是确定的事实。

不用再尝试,这个和尚他可能的另外一天值日的情况。因为肯定无解。


这就是我这个算法,优于“深度搜索”算法的原因。
ryuk33 2009-04-14
  • 打赏
  • 举报
回复
哈哈,这个问题太有意思了~~~

楼主的深度搜索算法,很直观,也很好理解。但效率太低,复杂度是O(n!)。

我的想法如下:

首先,做一个数组,每一个元素,是可以在该天值班的和尚的列表:
例如:

周一: [a, b]
周二: [b, c ,d]
...
周日: [a]

然后,就是计算的过程了:

1> 从这个数组中,找出可能的人数最少的一天。例如,周日,只有a可以在这一天值班。
2> 把a从另外一天中去除,因为他已经被安排在了周日。这个例子中,就是周一的a
3> 重复第1步。 这时,可以发现,周1又变成了只能是b值班。
4> 从周二中去除b以后
5> 假设接下来的周2,周3,周4,周5,周6。这5天,每天都刚好有两个人可以。那么,就使用楼主要深度遍历:
a) 周二选c, 然后开始重复第1步,得到所有的可能数
b) 周二选d, 然后开始重复第1步,得到所有的可能数


这个算法,基本上没有浪费计算的地方。是我能想到的最好的了。


hityct1 2009-04-14
  • 打赏
  • 举报
回复
[Quote=引用 6 楼 Dinelgua 的回复:]
一个和尚一周内必须值一天,至少值一天


和尚甲可以值 周二 周四

那么方案中 要么他再周二值日 要么再周四值日 不能同时值二和四 但 至少值一天
[/Quote]
有问题吧?一周7天,七个和尚,如果一个和尚一周内必须值一天,至少值一天 ,那每个和尚在一周只能且仅能值一天。不就是全排列问题吗?
我想应该是:一个和尚在一周能值0至2天。
T技术沙龙 2009-04-14
  • 打赏
  • 举报
回复
楼主的代码效率应该算是比较高了,可是中间的逻辑性好象不是很好,if语句中的排版有些混乱,读起来比较吃力

65,210

社区成员

发帖
与我相关
我的任务
社区描述
C++ 语言相关问题讨论,技术干货分享,前沿动态等
c++ 技术论坛(原bbs)
社区管理员
  • C++ 语言社区
  • encoderlee
  • paschen
加入社区
  • 近7日
  • 近30日
  • 至今
社区公告
  1. 请不要发布与C++技术无关的贴子
  2. 请不要发布与技术无关的招聘、广告的帖子
  3. 请尽可能的描述清楚你的问题,如果涉及到代码请尽可能的格式化一下

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