社区
数据结构与算法
帖子详情
请教高手一个关于回溯的算法
HuangRwen
2004-12-25 11:21:58
用回溯算法,编写一个函数fill(int num, int n),用0到num-1的数填充n*n的矩阵,要求填充的数不能重复,各行元素之和相等,各列元素之和也相同,输出所有可能的填充结果。
非常感谢!!
给出个大概算法也好。
...全文
383
22
打赏
收藏
请教高手一个关于回溯的算法
用回溯算法,编写一个函数fill(int num, int n),用0到num-1的数填充n*n的矩阵,要求填充的数不能重复,各行元素之和相等,各列元素之和也相同,输出所有可能的填充结果。 非常感谢!! 给出个大概算法也好。
复制链接
扫一扫
分享
转发到动态
举报
写回复
配置赞助广告
用AI写文章
22 条
回复
切换为时间正序
请发表友善的回复…
发表回复
打赏红包
Woodman007
2005-01-05
打赏
举报
回复
"各行元素之和相等,各列元素之和也相同",这个“每行之和”是确定的:
Σ第i行之和 = 0 +1 +2 +……+(n^2-1) , 而“每行之和”是相等的,所以
“每行之和” = [ 0 +1 +2 +……+(n^2-1)]/ n = [(n+1)(2n+1)/6]-1/n
“每列之和”也一样,所以算法可以是这样:每次填一行,每行之和为[(n+1)(2n+1)/6]-1/n,不合条件就回溯
baryjim
2005-01-01
打赏
举报
回复
的确如此,我也发现了这个情况,在递增或者递减顺序下,调试中我观察数据的变化情况,真的很难做!数据在及其缓慢向目标移动,真的很心急,如果是遗传算法直接来个变异就ok了。
我想,把数据顺序打乱,以任意顺序来做也应该不错。能尽快得出一个解,但是对输出所有解帮助不大呀
chenzhichao2008
2005-01-01
打赏
举报
回复
用回朔,可以再优化一下,将数字系列分成两半(高数区和小数区)
如(01234)和(56789)
填数时,从高数区取一个数,与低位区取一个数,分别填在对称的位置
再加一些条件限制如:每一行(列)之和不能小于最大数(9)
每一行(列)之和不能大于最大数与中间数之和(9+4(5)=13(14))
这样搜索范围就大大减小了
jp1984
2005-01-01
打赏
举报
回复
回朔的话本题不是个很好的例子,本题组合数虽然大,但是构造幻方有简便方法。
HuangRwen
2005-01-01
打赏
举报
回复
是回溯了,呵呵
加上递归和组合方面, mmmcd(超超)大哥能不能给点指导?谢谢
mmmcd
2005-01-01
打赏
举报
回复
构造一个幻方有很标准的方法。
楼主感兴趣的是回溯法还是幻方?
HuangRwen
2004-12-31
打赏
举报
回复
thank you so much, baryjim!!!!
baryjim
2004-12-31
打赏
举报
回复
我的方法是用交换的方式来给2维数组赋值的,所以不用考虑数字重复的情况,故是num!级别的!
当方阵为4×4的时候,就是16!了,所以算不出来结果,看来回溯在解决这个问题上效率捉襟见肘啊!!
建议楼主换方法吧!!
baryjim
2004-12-31
打赏
举报
回复
呜呜,没有实践就没有发言权啊!!看来jp1984(吕青萍C) 的悲观是有道理的!!我做的程序,当规模达到4的时候,几乎就不出结果了!!
#include<iostream.h>
#define length 3
#define limit length*length-1
#define total (1+(limit))*(limit)/(2*length)
int a[length][length];
int b[limit];
void output()
{
for(int i=0;i<length;i++){
for(int j=0;j<length;j++)
cout<<a[i][j]<<" ";
cout<<endl;
}
cout<<endl;
}
//这是排列问题,所以需要用交换函数来避免重复的数字写入
void swap(int& i,int& j)
{
int k=i;
i=j;
j=k;
}
void fill(int num,int t)
{
int k=0;
int i=0;
int j=0;
int ii=0;
if (t>limit) {
cout<<"mark"<<endl;
output();
return;
}
int row=t/length;//递归n层当前所在的行和列
int column=t%length;
for(ii=t;ii<=limit;ii++){
swap(b[t],b[ii]);
for(int i=0;i<=limit;i++)
a[i/length][i%length]=b[i];//赋值
//当前赋值过的所有数组元素是否满足条件,如果有一个不满足的,则回溯
for(i=0;i<=row;i++){//检查行元素之和
k=0;
for(j=0;j<=column;j++)
k+=a[i][j];
if (k>total) {swap(b[ii],b[t]);return;}
}
for(i=0;i<=row;i++){//检查列元素之和
k=0;
for(j=0;j<=column;j++)
k+=a[j][i];
if (k>total) {swap(b[ii],b[t]);return;}
}
fill(num,t+1);//递归到下一层
swap(b[ii],b[t]);
}
}
void main()
{
for(int i=0;i<=limit;i++)
b[i]=i;
fill(limit,0);
}
baryjim
2004-12-30
打赏
举报
回复
to rickone(RickOne):
我记得幻方比这个要求高吧!!斜线也要求相等,楼主这个没要求,所以会丢解的!!
HuangRwen
2004-12-30
打赏
举报
回复
我觉得也是啊,呵呵
有没谁方便写出比较详细一点的实现供大家
参考一下?谢谢
baryjim
2004-12-30
打赏
举报
回复
楼上说的是最坏情况下,但是到达最坏情况下的概率也是很低的,所以效果没有你想象的那么糟糕。
回溯自然不是所有空格都满的情况下判断是否合适,那样就是穷举了,没填充一个空格就要判断一下,发现不合适马上回溯!!
jp1984
2004-12-30
打赏
举报
回复
构造幻方。。直接算的话 每个格要试探 num - 1次,一共n^2格。。效率太夸张了 O(num ^(n^2))
sgal
2004-12-30
打赏
举报
回复
楼主你搞懂了?
我没看懂,你在什么时候判断是否回溯?等所有的空格都填好了再判断吗?
显然不行噻,那什么时候呢?
望指教~~~
HuangRwen
2004-12-30
打赏
举报
回复
谢谢以上各位
mmmcd
2004-12-29
打赏
举报
回复
fill(int num,int n)
{
if (n==num && 各行元素之和相等,各列元素之和也相同) output();/*直接计算吧*/
for(int i=0;i<num;i++){
a[n]=i;//这里a[n]相当于把二维矩阵映射到1维上
if (condition()==true)
fill(num,n+1);
}
}
rickone
2004-12-29
打赏
举报
回复
直接用回溯会算死人的啊~~~
看看有关幻方的构造方法吧。
HuangRwen
2004-12-29
打赏
举报
回复
关键是每次填一行和一列,而不是填一个数,这个理解有没有错?
回溯时退一行还是一个数?这个condition()应该怎么写。
希望可以得到够详细一些的解释,非常感谢 mmmcd(超超),谢谢!!
谢谢baryjim
要是分不够的话可以再加.
HuangRwen
2004-12-27
打赏
举报
回复
thank you two above so much!! but there seems sth do not match the
damands--"各行元素之和相等,各列元素之和也相同".
could you please explain more explitely to me?
any reply would be appreciate.
thank you,Baryjim
baryjim
2004-12-26
打赏
举报
回复
楼主啊!!fill(int num, int n),里面得n应该不是n阶矩阵,而是递归得层次!!
用回溯的方法!!
fill(int num,int n)
{
if (n==num) output();
for(int i=0;i<num;i++){
a[n]=i;//这里a[n]相当于把二维矩阵映射到1维上
if (condition()==true)
fill(num,n+1);
}
}
加载更多回复(2)
php
回溯
算法
,
一个
用PHP实现的
回溯
算法
的例子
本文通过
一个
PHP代码示例介绍了如何运用
回溯
算法
解决一头大牛、一头中牛和两头小牛驮大米的问题。通过递归和条件判断找到满足100袋大米的最优解,帮助PHP初学者理解
回溯
算法
的应用。
一个
框架解决
回溯
算法
本文深入浅出地介绍了
回溯
算法
的概念及其应用。通过实例解析,读者可以了解到如何使用
回溯
法解决复杂问题,并掌握其核心思想及实现框架。
算法
学习之
回溯
算法
:通过
一个
例子学会
回溯
算法
——从方法论到实际应用
本文介绍了
回溯
算法
,其核心思想是“试探 + 剪枝”,基本步骤包括选择、约束、完成和
回溯
。通过整数拆分问题实例,展示了
回溯
算法
的应用,还总结了其关键点,如递归
回溯
、剪枝优化和全局状态维护,最后提及了该
算法
在八皇后、数独等问题中的扩展应用。
写
一个
java
回溯
算法
该文章展示了
一个
使用Java编写的
回溯
算法
示例,主要功能是找到数组中数的组合,使其和等于给定的目标值。代码从数组的特定索引开始搜索,当目标值等于0时,打印解决方案。,
写
一个
递归与
回溯
算法
本文深入探讨了递归与
回溯
算法
,通过实例解析了递归的本质和在解决实际问题中的应用,如斐波那契数列、二叉树的前中后序遍历。递归的关键在于终止条件和子问题的解决,与栈紧密相关。文章还介绍了如何运用递归解决括号匹配、二叉树深度、字符串匹配等问题,强调了递归在解决复杂问题时的思维清晰性和效率。
数据结构与算法
33,026
社区成员
35,336
社区内容
发帖
与我相关
我的任务
数据结构与算法
数据结构与算法相关内容讨论专区
复制链接
扫一扫
分享
社区描述
数据结构与算法相关内容讨论专区
社区管理员
加入社区
获取链接或二维码
近7日
近30日
至今
加载中
查看更多榜单
社区公告
暂无公告
试试用AI创作助手写篇文章吧
+ 用AI写文章