❶ 回溯算法,用c语言实现
这个算法应该不难,基本和全排列的算法类似,只不过判断条件不是n=1, 而是在判断已经取得的数的和>=M为终止条件。
具体的算法,我给个大概流程吧
int lst[N]; //保存选取的数
int index = 0; //lst中最后的一个数的位置
func(W, N)
{
if(N == 0) //遍历完毕 返回
return;
for(i=0 to N)
{
if( W[i][1] != -1 ) //判断是否已经读取当前值
{
lst[index++] = W[i][0] //当前值加入到保存数组
W[i][1] = -1; //设置当前值已经读取,不可再读
if(check() == 0)
{
func(W, N-1); //大小不够M,继续往下读
}
else if(check() == 1)
{
print(lst); //和为M,输出
}
lst[--index] = 0; //回溯,寻找下一组解
W[i][1] = 0;
}
}
}
check()
{
if(sum(lst) > W)
return -1;
if(sum(lst) < W)
return 0;
return 1;
}
❷ 在C# 使用回溯算法,得到一个值后 ,直接结束算法,开始其他程序
回溯算法一般要记录所有值的结果到一个类似于数组的数据结构里面,如果想要提前结束回溯算法,就判断一下数组里面是不是已经有结果了。如果有了,直接就可以返回了。
❸ c语言回溯算法
if(n==7||a[n+1][i]!=1&&a[n+1][i+1]!=1&&a[n+1][i-1]!=1)
这行的代码是判断是否可以放皇后的句子。如果可以就将所在位置置 1 。后面也就是这样做判断的。这个程序应当有问题,其中try应当是C语言中一个关键字啊,不可以这么用。
就我的看法:八皇后的问题应当用递归加回溯会都到更好的代码,我写过,不过也快忘了。
❹ 用伪码描述回溯法搜索排列树的算法模式。
希望能帮到你!!!
❺ 什么是回溯算法
回溯算法也叫试探法,它是一种系统地搜索问题的解的方法。回溯算法的基本思想是:从一条路往前走,能进则进,不能进则退回来,换一条路再试。用回溯算法解决问题的一般步骤为: 1、定义一个解空间,它包含问题的解。 2、利用适于搜索的方法组织解空间。 3、利用深度优先法搜索解空间。 4、利用限界函数避免移动到不可能产生解的子空间。 问题的解空间通常是在搜索问题的解的过程中动态产生的,这是回溯算法的一个重要特性。 1.跳棋问题: 33个方格顶点摆放着32枚棋子,仅中央的顶点空着未摆放棋子。下棋的规则是任一棋子可以沿水平或成垂直方向跳过与其相邻的棋子,进入空着的顶点并吃掉被跳过的棋子。试设计一个算法找出一种下棋方法,使得最终棋盘上只剩下一个棋子在棋盘中央。 算法实现提示 利用回溯算法,每次找到一个可以走的棋子走动,并吃掉。若走到无子可走还是剩余多颗,则回溯,走下一颗可以走动的棋子。当吃掉31颗时说明只剩一颗,程序结束。 2.中国象棋马行线问题: 中国象棋半张棋盘如图1(a)所示。马自左下角往右上角跳。今规定只许往右跳,不许往左跳。比如 图4(a)中所示为一种跳行路线,并将所经路线打印出来。打印格式为: 0,0->2,1->3,3->1,4->3,5->2,7->4,8… 算法分析: 如图1(b),马最多有四个方向,若原来的横坐标为j、纵坐标为i,则四个方向的移动可表示为: 1: (i,j)→(i+2,j+1); (i<3,j<8) 2: (i,j)→(i+1,j+2); (i<4,j<7) 3: (i,j)→(i-1,j+2); (i>0,j<7) 4: (i,j)→(i-2,j+1); (i>1,j<8) 搜索策略: S1:A[1]:=(0,0); S2:从A[1]出发,按移动规则依次选定某个方向,如果达到的是(4,8)则转向S3,否则继续搜索下 一个到达的顶点; S3:打印路径。 算法设计: procere try(i:integer); {搜索} var j:integer; begin for j:=1 to 4 do {试遍4个方向} if 新坐标满足条件 then begin 记录新坐标; if 到达目的地 then print {统计方案,输出结果} else try(i+1); {试探下一步} 退回到上一个坐标,即回溯; end; end;
❻ 应用问题求解,加油站有效加油位问题!
1.已知有
3
个物品:(w1,w2,w3)=(12,10,6),(p1,p2,p3)=(15,13,10),背包的容积
M=20,根据
0-1
背
包动态规划的递推式求出最优解。
2.按要求完成以下关于排序和查找的问题。
①对数组
A={15,29,135,18,32,1,27,25,5},用快速排序方法将其排成递减序。
②请描述递减数组进行二分搜索的基本思想,并给出非递归算法。
③给出上述算法的递归算法。
④使用上述算法对①所得到的结果搜索如下元素,并给出搜索过程:18,31,135。
3.已知
1
(
)
*
(
)
i
i
k
k
ij
r
r
A
a
+
=
,
k
=1,2,3,4,5,6,
r
1
=5,
r
2
=10,
r
3
=3,
r
4
=12,
r
5
=5,
r
6
=50,
r
7
=6,
求矩阵链积
A
1
×A
2
×A
3
×A
4
×A
5
×A
6
的最佳求积顺序(要求给出计算步骤)
。
4.
根
据
分
枝
限
界
算
法
基
本
过
程
,
求
解
0-1
背
包
问
题
。
已
知
n=3,M=20
,
(w1,w2,w3)=(12,10,6),(p1,p2,p3)=(15,13,10)。
5.试用贪心算法求解汽车加油问题:
已知一辆汽车加满油后可行驶
n
公里,
而旅途中有若干个加油站。
试设计一个有效算法,指出应在哪些加油站停靠加油,使加油次数最少,请写出该算法。
6.试用动态规划算法实现下列问题:设
A
和
B
是两个字符串。我们要用最少的字符操作,将字符串
A
转换为字符串
B,这里所说的字符操作包括:
①删除一个字符。
②插入一个字符。
③将一个字符改为另一个字符。
请写出该算法。
7.对于下图使用
Dijkstra
算法求由顶点
a
到顶点
h
的最短路径。
8.试写出用分治法对数组
A[n]实现快速排序的算法。
9.有
n
个活动争用一个活动室。
已知活动
i
占用的时间区域为[s
i
,
f
i
],
活动
i,j
相容的条件是:
sj≥f
i
,问题的解表示为(x
i
|
x
i
=1,2…,n,),x
i
表示顺序为
i
的活动编号活动,求一个相容的活动子
集,且安排的活动数目最多。
10.设
x
1
、
x
2
、
x
3
是一个三角形的三条边,而且
x
1
+x
2
+x
3
=14。请问有多少种不同的三角形?给出解答过
程。
11.设数组
A
有
n
个元素,需要找出其中的最大最小值。
①请给出一个解决方法,并分析其复杂性。
②把
n
个元素等分为两组
A1
和
A2,分别求这两组的最大值和最小值,然后分别将这两组的最大值
和最小值相比较,求出全部元素的最大值和最小值。如果
A1
和
A2
中的元素多于两个,则再用上述
方法各分为两个子集。直至子集中元素至多两个元素为止。这是什么方法的思想?请给出该方法的
算法描述,并分析其复杂性。
12.有
n
个程序和长度为
L
的磁带,
程序
i
的长度为
a
i
,
已知
L
a
n
i
i
≻
∑
=
1
,
求最优解(x
i
,
x
2
,
...,
x
i
,
…,
x
n
),x
i
=0,1,
x
i
=1,表示程序
i
存入磁带,x
i
=0,表示程序
i
不存入磁带,满足
L
a
x
n
i
i
i
≤
∑
=
1
,
且存放的程序数目最多。
13.试用分治法实现有重复元素的排列问题:设
)
,...,
,
{
2
1
n
r
r
r
R
=
是要进行排列的
n
个元素,其中元素
n
r
r
r
,...,
,
2
1
可能相同,试设计计算
R
的所有不同排列的算法。
14.试用动态规划算法实现
0-1
闭包问题,请写出该算法。
15.试用贪心算法求解下列问题:将正整数
n
分解为若干个互不相同的自然数之和,使这些自然数的乘
积最大,请写出该算法。
16.试写出用分治法对一个有序表实现二分搜索的算法。
17.试用动态规划算法实现最长公共子序列问题,请写出该算法。
18.假设有
7
个物品,它们的重量和价值如下表所示。若这些物品均不能被分割,且背包容量
M=150,
使用回溯方法求解此背包问题,请写出状态空间搜索树。
物品
A
B
C
D
E
F
G
重量
35
30
60
50
40
10
25
价值
10
40
30
50
35
40
30
19.求解子集和问题:对于集合
S={1,2
,6,8},求子集,要求该子集的元素之和
d=9。
①画出子集和问题的解空间树;
②该树运用回溯算法,写出依回溯算法遍历节点的顺序;
③如果
S
中有
n
个元素,指定
d,用伪代码描述求解子集和问题的回溯算法。
20.求解填字游戏问题:在
3×3
个方格的方阵中要填入数字
1
到
N(N≥10)内的某
9
个数字,每个方
格填一个整数,似的所有相邻两个方格内的两个整数之和为质数。试采用回溯法写出满足这个要求
的一种数字填法的算法和满足这个要求的全部数字填法的算法。
21.试用动态规划算法实现最大子矩阵和问题:
求
n
m
×
矩阵
A
的一个子矩阵,
使其各元素之和为最大。
22.试用回溯法解决下列整数变换问题:关于整数
i
的变换
f
和
g
定义如下:
⎣
⎦
2
/
)
(
;
3
)
(
i
i
g
i
i
f
=
=
。
对于给定的两个整数
n
和
m
,要求用最少的变换
f
和
g
变换次数将
n
变为
m
。
23.关于
15
谜问题。在一个
4×4
的方格的棋盘上,将数字
1
到
15
代表的
15
个棋子以任意的顺序置入
各方格中,空出一格。要求通过有限次的移动,把一个给定的初始状态变成目标状态。移动的规则
是:每次只能把空格周围的四格数字(棋子)中的任意一个移入空格,从而形成一个新的状态。为
了有效的移动,设计了估值函数
C
1
(x),表示在结点
x
的状态下,没有到达目标状态下的正确位置
的棋子的个数。
❼ Pascal算法之回溯及递推详细介绍、
递归 递归是计算机科学的一个重要概念,递归的方法是程序设计中有效的方法,采用递归编写程序能是程序变得简洁和清晰.2.1 递归的概念
1.概念一个过程(或函数)直接或间接调用自己本身,这种过程(或函数)叫递归过程(或函数).如:procere a; begin . . . a; . . .end;这种方式是直接调用.又如: procere b; procere c; begin begin . . . . . . c; b; . . . . . .end; end;这种方式是间接调用.例1计算n!可用递归公式如下: 1 当 n=0 时 fac(n)={n*fac(n-1) 当n>0时可编写程序如下:program fac2;varn:integer;function fac(n:integer):real;beginif n=0 then fac:=1 else fac:=n*fac(n-1)end;beginwrite('n=');readln(n);writeln('fac(',n,')=',fac(n):6:0);end.例2 楼梯有n阶台阶,上楼可以一步上1阶,也可以一步上2阶,编一程序计算共有多少种不同的走法.设n阶台阶的走法数为f(n)显然有 1 n=1 f(n)={2 n=2 f(n-1)+f(n-2) n>2可编程序如下:program louti;var n:integer;function f(x:integer):integer;beginif x=1 then f:=1 elseif x=2 then f:=2 else f:=f(x-1)+f(x-2);end;beginwrite('n=');read(n);writeln('f(',n,')=',f(n))end.2.2 如何设计递归算法
1.确定递归公式2.确定边界(终了)条件练习:用递归的方法完成下列问题1.求数组中的最大数2.1+2+3+...+n3.求n个整数的积4.求n个整数的平均值5.求n个自然数的最大公约数与最小公倍数6.有一对雌雄兔,每两个月就繁殖雌雄各一对兔子.问n个月后共有多少对兔子?7.已知:数列1,1,2,4,7,13,24,44,...求数列的第 n项. 2.3典型例题例3 梵塔问题 如图:已知有三根针分别用1,2,3表示,在一号针中从小放n个盘子,现要求把所有的盘子 从1针全部移到3针,移动规则是:使用2针作为过度针,每次只移动一块盘子,且每根针上不能出现大盘压小盘.找出移动次数最小的方案. 程序如下:program fanta;varn:integer;procere move(n,a,b,c:integer);beginif n=1 then writeln(a,'--->',c)else beginmove(n-1,a,c,b);writeln(a,'--->',c);move(n-1,b,a,c);end;end;beginwrite('Enter n=');read(n);move(n,1,2,3);end.例4 快速排序快速排序的思想是:先从数据序列中选一个元素,并将序列中所有比该元素小的元素都放到它的右边或左边,再对左右两边分别用同样的方法处之直到每一个待处理的序列的长度为1, 处理结束.程序如下:program kspv;
const n=7;
type
arr=array[1..n] of integer;
var
a:arr;
i:integer;
procere quicksort(var b:arr; s,t:integer);
var i,j,x,t1:integer;
begin
i:=s;j:=t;x:=b[i];
repeat
while (b[j]>=x) and (j>i) do j:=j-1;
if j>i then begin t1:=b[i]; b[i]:=b[j];b[j]:=t1;end;
while (b[i]<=x) and (i<j) do i:=i+1;
if i<j then begin t1:=b[j];b[j]:=b[i];b[i]:=t1; end
until i=j;
b[i]:=x;
i:=i+1;j:=j-1;
if s<j then quicksort(b,s,j);
if i<t then quicksort(b,i,t);
end;
begin
write('input data:');
for i:=1 to n do read(a[i]);
writeln;
quicksort(a,1,n);
write('output data:');
for i:=1 to n do write(a[i]:6);
writeln;
end.练习:1.计算ackerman函数值: n+1 m=0 ack(m,n)={ ack(m-1,1) m<>0 ,n=0 ack(m-1,ack(m,n-1)) m<>0,n<>0 求ack(5,4)
回溯 回溯是按照某种条件往前试探搜索,若前进中遭到失败,则回过头来另择通路继续搜索.3.1 回溯的设计 1.用栈保存好前进中的某些状态.2.制定好约束条件例1由键盘上输入任意n个符号;输出它的全排列.program hh;
const n=4;
var i,k:integer;
x:array[1..n] of integer;
st:string[n];
t:string[n];
procere input;
var i:integer;
begin
write('Enter string=');readln(st);
t:=st;
end;
function place(k:integer):boolean;
var i:integer;
begin
place:=true;
for i:=1 to k-1 do
if x[i]=x[k] then
begin place:=false; break end ;
end;
procere print;
var i:integer;
begin
for i:=1 to n do write(t[x[i]]);
writeln;
end;
begin
input;
k:=1;x[k]:=0;
while k>0 do
begin
x[k]:=x[k]+1;
while (x[k]<=n) and (not place(k)) do x[k]:=x[k]+1;
if x[k]>n then k:=k-1
else if k=n then print
else begin k:=k+1;x[k]:=0 end
end ;
end.例2.n个皇后问题:program hh;
const n=8;
var i,j,k:integer;
x:array[1..n] of integer;
function place(k:integer):boolean;
var i:integer;
begin
place:=true;
for i:=1 to k-1 do
if (x[i]=x[k]) or (abs(x[i]-x[k])=abs(i-k)) then
place:=false ;
end;
procere print;
var i:integer;
begin
for i:=1 to n do write(x[i]:4);
writeln;
end;
begin
k:=1;x[k]:=0;
while k>0 do
begin
x[k]:=x[k]+1;
while (x[k]<=n) and (not place(k)) do x[k]:=x[k]+1;
if x[k]>n then k:=k-1
else if k=n then print
else begin k:=k+1;x[k]:=0 end
end ;end.回溯算法的公式如下:3.2 回溯算法的递归实现由于回溯算法用一栈数组实现的,用到栈一般可用递归实现。上述例1的递归方法实现如下:program hh;
const n=4;
var i,k:integer;
x:array[1..n] of integer;
st:string[n];
t:string[n];
procere input;
var i:integer;
begin
write('Enter string=');readln(st);
t:=st;
end;
function place(k:integer):boolean;
var i:integer;
begin
place:=true;
for i:=1 to k-1 do
if x[i]=x[k] then
begin place:=false; break end ;
end;
procere print;
var i:integer;
begin
for i:=1 to n do write(t[x[i]]);
writeln;readln;
end;
procere try(k:integer);
var i :integer;
begin
if k=n+1 then begin print;exit end;
for i:=1 to n do
begin
x[k]:=i;
if place(k) then try(k+1)
end
end;
begin
input;
try(1);
end.例2:n皇后问题的递归算法如下:程序1:program hh;
const n=8;
var i,j,k:integer;
x:array[1..n] of integer;
function place(k:integer):boolean;
var i:integer;
begin
place:=true;
for i:=1 to k-1 do
if (x[i]=x[k]) or (abs(x[i]-x[k])=abs(i-k)) then
place:=false ;
end;
procere print;
var i:integer;
begin
for i:=1 to n do write(x[i]:4);
writeln;
end;
procere try(k:integer);
var i:integer;
begin
if k=n+1 then begin print; exit end;
for i:= 1 to n do
begin
x[k]:=i;
if place(k) then try(k+1);
end;
end ;
begin
try(1);
end.程序2:说明:当n=8 时有30条对角线分别用了l和r数组控制,用c数组控制列.当(i,j)点放好皇后后相应的对角线和列都为false.递归程序如下:program nhh;
const n=8;
var s,i:integer;
a:array[1..n] of byte;
c:array[1..n] of boolean;
l:array[1-n..n-1] of boolean;
r:array[2..2*n] of boolean;
procere output;
var i:integer;
begin
for i:=1 to n do write(a[i]:4);
inc(s);writeln(' total=',s);
end;
procere try(i:integer);
var j:integer;
begin
for j:=1 to n do
begin
if c[j] and l[i-j] and r[i+j] then
begin
a[i]:=j;c[j]:=false;l[i-j]:=false; r[i+j]:=false;
if i<n then try(i+1) else output;
c[j]:=true;l[i-j]:=true;r[i+j]:=true;
end;
end;
end;
begin
for i:=1 to n do c[i]:=true;
for i:=1-n to n-1 do l[i]:=true;
for i:=2 to 2*n do r[i]:=true;
s:=0;try(1);
writeln;
end.练习:1.找出所有从m个元素中选取n(n<=m)元素的组合。2.设有A,B,C,D,E 5人从事j1,j2,j3,j4,j5 5项工作每人只能从事一项,它们的效益表如下:求最佳安排,使效益最高.3.N个数中找出M个数(从键盘上输入正整数N,M后再输入N个正数),要求从N个数中找出若干个数,使它们的和为M,把满足条件的数组找出来,并统计组数.4.地图着色。如下图12个区域用4种颜色着色要求相邻的区域着不同的颜色5.将任意一正整数(1<n<100)分解成若干正整数的和. 如:4=1+1+1+1 =2+1+1 =2+2 =3+1.
❽ c语言高手帮个忙(圆排列回溯算法)
数组下标要从0开始使用啊
a=(float *)malloc(C.n*sizeof(float));
b=(float *)malloc((C.n+1)*sizeof(float));//记录每次的排列
rf=(int *)malloc((C.n+1)*sizeof(int));//标记已经使用的圆
这时的C.n还没有值,就malloc是没有意义的!!
❾ 硬币兑换问题回溯法伪代码
A数组用来存放硬币,数值1代表正面,0代表反面;
static int s;s是存放每列状态的数初始为0代表一列都没翻,第几位为1就代表第几列被翻转
int turncoin(A,S,N,n) //A(N*9数组) ,N是行数 n代表当次翻哪一列 初次调用n=0,代表第一列
{ int i=1;//因为每列只有两种状态,所以每列只翻一次
static int max=0;//用来存放翻转后正面朝上的最大硬币数;
static int S;//大S用来存储当前硬币堆的翻转状态
do {turncoin(A,S,N,n+1);if (n==8){ int tem=sum //sum为遍历A数组,所有元素之和(即为当前正面朝上的硬币数)
if(sum>max){S=s; //把当前翻转状态存储到S,S内总是存储着拥有正面朝上硬币数量最高的一种翻转状态;}}}while(i--&&transform(N,n));
//transform()函数翻转第N列的硬币 并且对s的第n位置一 成功返回ture 并且对是 实现就是for(i=0;
i
拓展资料:
一、题目描述:
一个翻硬币的游戏,有N(N <=10000)行硬币,每行有九个硬币,排成一个N*9的方阵,有的硬币正面朝上,有的反面朝上。我们每次可把一整行或者一整列的所有硬币翻过来,请问怎么翻,使得正面朝上的硬币尽量多(翻硬币无次数限制)。
二、思路分析:
枚举2^9种列的翻法。
遍历N行,如果某行正面朝上的少,翻之;如果正面朝上的多,不翻
记下使得正面最多的方法即可
耗时O(2^9 * N)
这个得到的是最优解.用位运算效率还是很高的.
对每一列,都用一个9位的数表示,一共有N个
然后便利所有的9位状态,(000000000)-(111111111) (二进制)
对于每个状态,都与这N个数异或,每次异或后累加所有的1的值假设为k,如果k小于5则k=9-k.
对N个数累加所有的k,得到最终累加和.
求出所有状态下累加和最大的,就是正面朝上的硬币尽量多的个数.
翻面的方法横列分别是最优解的8位状态和与之对应的每个数异或后累加和k是否小于5.
❿ 用递归函数设计八皇后问题的回溯算法C++代码
解析:递归实现n皇后问题。
算法分析:
数组a、b、c分别用来标记冲突,a数组代表列冲突,从a[0]~a[7]代表第0列到第7列。如果某列上已经有皇后,则为1,否则为0。
数组b代表主对角线冲突,为b[i-j+7],即从b[0]~b[14]。如果某条主对角线上已经有皇后,则为1,否则为0。
数组c代表从对角线冲突,为c[i+j],即从c[0]~c[14]。如果某条从对角线上已经有皇后,则为1,否则为0。
代码如下:
#include <stdio.h>
static char Queen[8][8];
static int a[8];
static int b[15];
static int c[15];
static int iQueenNum=0; //记录总的棋盘状态数
void qu(int i); //参数i代表行
int main()
{
int iLine,iColumn;
//棋盘初始化,空格为*,放置皇后的地方为@
for(iLine=0;iLine<8;iLine++)
{
a[iLine]=0; //列标记初始化,表示无列冲突
for(iColumn=0;iColumn<8;iColumn++)
Queen[iLine][iColumn]='*';
}
//主、从对角线标记初始化,表示没有冲突
for(iLine=0;iLine<15;iLine++)
b[iLine]=c[iLine]=0;
qu(0);
return 0;
}
void qu(int i)
{
int iColumn;
for(iColumn=0;iColumn<8;iColumn++)
{
if(a[iColumn]==0&&b[i-iColumn+7]==0&&c[i+iColumn]==0)
//如果无冲突
{
Queen[i][iColumn]='@'; //放皇后
a[iColumn]=1; //标记,下一次该列上不能放皇后
b[i-iColumn+7]=1; //标记,下一次该主对角线上不能放皇后
c[i+iColumn]=1; //标记,下一次该从对角线上不能放皇后
if(i<7) qu(i+1); //如果行还没有遍历完,进入下一行
else //否则输出
{
//输出棋盘状态
int iLine,iColumn;
printf("第%d种状态为:\n",++iQueenNum);
for(iLine=0;iLine<8;iLine++)
{
for(iColumn=0;iColumn<8;iColumn++)
printf("%c ",Queen[iLine][iColumn]);
printf("\n");
}
printf("\n\n");
}
//如果前次的皇后放置导致后面的放置无论如何都不能满足要求,则回溯,重置
Queen[i][iColumn]='*';
a[iColumn]=0;
b[i-iColumn+7]=0;
c[i+iColumn]=0;
}
}
}