當前位置:首頁 » 編程語言 » C語言回溯剪枝
擴展閱讀
webinf下怎麼引入js 2023-08-31 21:54:13
堡壘機怎麼打開web 2023-08-31 21:54:11

C語言回溯剪枝

發布時間: 2023-05-30 07:54:40

㈠ 關於回溯法c語言

具體你的演算法我沒仔細看,但是沒有輸出是因為肢老羨你的起始循含納環條件不滿足,l=1; 緊接著while(l<歷拍0)肯定是不會進入循環的。

㈡ 回溯法的用回溯法解題的一般步驟

(1)針對所給問題,定義問題的解空間;
(2)確定易於搜索的解空間結構;
(3)以深度優先方式搜索解賀腔空間,並在搜索過程中用剪枝函數避免無效搜索。
回溯法C語言舉例
八皇後問題是能用回溯法解決的一個經典問題。
八皇後問題是一個古老而著名的問題。該問銷差題是十九世紀著名的數學家高斯1850年提出:在8X8格的國際象棋上擺放八個皇後,使其不能互相攻擊,即任意兩個皇後都不能處於同一行、同一列或同一對角線上,問有多少種擺法。引入一個整型一維數組col[]來存放最終結果,col[i]就表示在棋盤第i列、col[i]行有一個皇後,為了使程序再找完了全部解後回到最初位置,設定col[0]的初值為0,即當回溯到第0列時,說明以求得全部解,結束程序運行。為了方便演算法的實現,引入三個整型數組來表示當前列在三個方向上禪斗衫的狀態 :
a[] a[i]=0表示第i行上還沒有皇後;
b[] b[i]=0表示第i列反斜線/上沒有皇後;
c[] c[i]=0表示第i列正斜線上沒有皇後。
棋盤中同一反斜線/上的方格的行號與列號之和相同;同一正斜線上的方格的行號與列號之差均相同,這就是判斷斜線的依據。
初始時,所有行和斜線上都沒有皇後,從第1列的第1行配置第一個皇後開始,在第m列,col[m]行放置了一個合理的皇後,准備考察第m+1列時,在數組a[],b[]和c[]中為第m列,col[m]行的位置設定有皇後的標志;當從第m列回溯到m-1列時,並准備調整第m-1列的皇後配置時,清除在數組a[],b[]和c[]對應位置的值都為1來確定。 #include<stdio.h>
#include<stdlib.h>
#define Queens 8
int a[Queens+1]; //八皇後問題的皇後所在每一行位置,從1開始算
int main()
{
int i,k,flag,not_finish=1,count=0;
i=1;//初始
a[1]=1;
printf(the possible configuration of 8 queesns are: );
while(not_finish) //not_finsh=1:處理未結束
{
while(not_finish && i<Queens+1) //處理未結束
{
for(flag=1,k=1;flag && k<i;k++)//判斷是否有多個皇後在同一行
if(a[k]==a[i])
flag=0;
for(k=1;flag && k<i;k++) //判斷是否有多個皇後在對角線
if((a[i]==a[k]-(k-i))||(a[i]==a[k]+(k-i)))
flag=0;
if(!flag) //若存在矛盾 重設第i個元素
{
if(a[i]==a[i-1]) //若a[i]的值已經已經一圈追上a[i-1]的值
{
i--; //退回一步 重新試探處理前一個元素
if(i>1 && a[i]==Queens)
a[i]=1; // 當a[i]為 Queens時 將a[i]的值重置
else
if(i==1 && a[i]==Queens)//當第一未位的值達到Queens時結束
not_finish=0;
else
a[i]++;
}
else
if(a[i]==Queens)
a[i]=1;
else
a[i]++;
}
else
if(++i<=Queens) //若前一個元素的值為Queens
if(a[i-1]==Queens)
a[i]=1;
else //否則元素為前一個元素的下一個值
a[i]=a[i-1]+1;
}
if (not_finish)
{
++count;
printf((count-1)%3?[%2d]:: [%2d]:,count);
for(k=1;k<=Queens;k++) //輸出結果
printf(%d,a[k]);
if(a[Queens-1]<Queens)
a[Queens-1]++;
else
a[Queens-1]=1;
i=Queens-1;
}
}
system(pause);
} var
n,k,t,i:longint;
x:array[1..100] of integer;
function pa(k:integer):boolean;
begin
pa:=true;
for i:=1 to k-1 do
if (x[i]=x[k]) or (abs(x[i]-x[k])=abs(i-k)) then pa:=false;
end;
procere try(k:integer);
var
i:integer;
begin
if k>n then
begin
t:=t+1;
exit;
end;
for i:=1 to n do
begin
x[k]:=i;
if pa(k) then try(k+1);
end;
end;
begin
read(n);
t:=0;
try(1);
write(t);
end. #include
#include
#define m 5
#define n 6
int sf=0;
int mase[m][n]={{0,0,0,1,0,0},{0,1,0,0,0,0},{0,1,1,1,1,0},{0,0,0,0,0,1},{1,0,1,1,0,0}};
void search(int x,int y)
{
if((x==m-1)&&(y==n-1))
sf=1;
else
{
mase[x][y]=1;
if((sf!=1)&&(y!=n-1)&&mase[x][y+1]==0)
search(x,y+1);
if((sf!=1)&&(x!=m-1)&&mase[x+1][y]==0)
search(x+1,y);
if((sf!=1)&&(y!=0)&&mase[x][y-1]==0)
search(x,y-1);
if((sf!=1)&&(x!=0)&&mase[x-1][y]==0)
search(x-1,y);
}
mase[x][y]=0;
if(sf==1)
mase[x][y]=5;//通過路徑用數字的表示
}
int main()
{
int i=0,j=0;
//clrscr();
search(0,0);
for(i=0;i<m;i++) p=></m;i++)>
{
for(j=0;j<n;j++) p=></n;j++)>
printf(%d,mase[i][j]);
printf( );
}
system(pause);
return 0;
}
回溯法解決迷宮問題PASCAL語言
program migong;
var
n,k,j,x,y:integer;
a:array[0..10000,0..10000] of integer;
b:array[0..1000000,0..2] of integer;
procere search(x,y,i:integer);
begin
a[x,y]:=1;
if (x=n) and (y=n) then
begin
for j:=1 to i-1 do
writeln(j,':(',b[j,1],',',b[j,2],')');
writeln(i,':(',x,',',y,')');
halt;
end;
if a[x-1,y]=0 then begin b[i,1]:=x;b[i,2]:=y;search(x-1,y,i+1);end;
if a[x+1,y]=0 then begin b[i,1]:=x;b[i,2]:=y;search(x+1,y,i+1);end;
if a[x,y-1]=0 then begin b[i,1]:=x;b[i,2]:=y;search(x,y-1,i+1);end;
if a[x,y+1]=0 then begin b[i,1]:=x;b[i,2]:=y;search(x,y+1,i+1);end;
a[x,y]:=0;
end;
begin
read(n);
for k:=1 to n do
for j:=1 to n do
read(a[k,j]);
for k:=0 to n+1 do
begin
a[k,0]:=-1;
a[k,n+1]:=-1;
a[n+1,k]:=-1;
a[0,k]:=-1;
end;
x:=1;y:=1;
if a[x+1,y]=0 then begin a[x,y]:=1;b[1,1]:=x;b[1,2]:=y;search(x+1,y,1);a[x,y]:=0;end;
if a[x,y+1]=0 then begin a[x,y]:=1;b[1,1]:=x;b[1,2]:=y;search(x,y+1,1);a[x,y]:=0;end;
end.

㈢ 求完全背包問題的代碼(C語言或C++版)或演算法

背包問題小結- []2006-07-28

做到背包問題覺得很有意思,寫寫看看。
完全背包問題可以用貪心演算法。
代碼如下:

program bag1;
const maxn=10;
var
goods:array[1..maxn,1..3] of integer;
s:array[1..maxn] of real;
i,j:integer;
m,n:integer;
y:integer;
x:real;
function max:integer;
var m:real;
i,j:integer;
begin
m:=0;
for i:=1 to n do
if (goods[i,3]=0) and (m max:=j;
end;

procere choose;
var i,j:integer;

begin
while y begin
if y begin
i:=max;
if m>=y+goods[i,1] then begin goods[i,3]:=1;x:=x+goods[i,2];y:=y+goods[i,1];end else
begin
x:=x+(m-y)*s[i];
y:=m;
end;
end;
end;
end;

begin
fillchar(goods,sizeof(goods),0);
assign(input,'b.txt');
reset(input);
readln(m,n);
for j:=1 to n do
read(goods[j,1]);
readln;
for j:=1 to n do
read(goods[j,2]);
for j:=1 to n do
s[j]:=goods[j,2]/goods[j,1];

close(input);
choose;
writeln(x:5:2);
end.
編得不是很好 ^-^ 獻丑了。

我來說說0/1背包問題。
狀態:當前物品n
算符:j=0(當前物品不放入背包) 或 j=1(當前物品放入背包)
這就很好說了,還是把yes函數一改,問題OK了。
代碼如下:

program bag2;
const maxn=10;
var i:integer;
goods:array[1..maxn,1..3] of integer;{原始數據}
s:array[1..maxn] of integer;{當前的狀態}
r:array[1..maxn] of integer;{當前的總質量}
m:integer;{背包容量}
max:integer;{物品個數}
procere try(n:integer);
var j:integer;

{function yes:boolean;
var k:integer;
t:integer;
mn:integer;
begin
mn:=0;
t:=goods[n,3];
goods[n,3]:=j;
for k:=1 to n do
if goods[k,3]=1 then inc(mn,goods[k,1]);
goods[n,3]:=t;
if mn>m then yes:=false else yes:=true;
end;}

begin
if n=max+1 then begin if x for i:=1 to max do s[i]:=goods[i,3]; {保存最優解}end
end else
begin
if r[n-1]>m then exit;{已超過背包總容量}
for j:=1 downto 0 do
begin
if j=1 then r[n]:=r[n-1]+goods[n,1];
if j=0 then r[n]:=r[n]-goods[n,1];
if {yes}r[n]<=m then begin goods[n,3]:=j;try(n+1);goods[n,3]:=0;end
end;
end;
end;

begin
assign(input,'b.txt');
reset(input);
readln(m,max);
for i:=1 to max do
read(goods[i,1]);
readln;
for i:=1 to max do
read(goods[i,2]);
close(input);
try(1);
for i:=1 to 7 do
write(s[i]:3);
writeln;
writeln(x);
end.

用yes 函數要從頭到當前求已裝入背包物品的總質量,時間效率不高。所以我們引入r[n]數組來記錄當前背包總質量(很好用!)注意用r[n-1]>m來做剪枝,以再次提高時間效率。

DC跟我說可以用二進制解此類問題。我覺得很有創意,也說說。比如8個物品,每個物品有0/1兩種狀態所以我們從(00000000)(二進制 )到(11111111)(二進制)循環即可。然後在分離十進制數對應起來即可。但在實際的操作中發現效率比回溯還低,我想有兩方面的原因:1、顯而易見,不可能做剪枝。2、每一次結果都要從1到8求和十效率降低。不過這確實是一種很新穎的演算法。

㈣ 回溯演算法,用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語言中的回溯法,舉一個簡單的小例子,說明回溯法的運行過程!

求子串位置
int Index(SString S, SString T, int pos) {
// 返回子串T在主串S中第pos個字元之後的位置。
// 若不存在,則檔簡函數值為0。
// 其中,T非空,1≤pos≤StrLength(S)。
int i = pos;
int j = 1;
while (i <= S[0] && j <= T[0]) {
if (S[i] == T[j]) { // 繼續比較後繼字元侍畝
++i;
++j;
} else { // 指針老蠢森後退重新開始匹配
i = i-j+2;
j = 1;
}
}
if (j > T[0]) return i-T[0];
else return 0;
} // Index

㈥ 請教一下c語言漢諾塔問題代碼不明白之處

哈哈,給你解釋下
首先你得明白這是用函數遞歸調用的方法,遞歸就不用我說磨滾了,看代碼
void hanoi(int n,char one,char two,char three)
{
void move(char x,char y);
if(n==1)
move(one,three);
//這個if語句,當盤子只有一個的時候,當然直接從第一根柱子(one)移到第//三根柱子(three)上就OK了,move(one,three)就這個意思!

else
{
hanoi(n-1,one,three,two);//當有n個盤子,按照遞歸法,調用hannoi,先把//上面的n-1個盤子從第一根柱子(one)藉助第三根柱子(three)移到第二根柱瞎宏//子上(two)。

move(one,three);//上面已把n-1個盤子移到第磨游冊二根柱子上了,再將第一根柱//子剩下的一個盤子也就是最大的盤子從one移到three,明白?

hanoi(n-1,two,one,three);
/*移動好了最大的一個盤子,剩下n-1個盤子在two上,這時我們可以把第二根柱子與第一個柱//子的位置交換下,也就是標號為two的排第一,one排第二,three排第三。
這里的hanoi(n-1,two,one,three)對應
void hanoi(int n,char one,char two,char three),只是盤子變成n-1
個,標號為two的柱子排第一了,下面要做的就是把two上上面的n-2個盤子藉助three移到one上,再把剩下的一個移到第三個,再調換one 和two位置。
如此重復!注意轉換位置只是我們頭腦中的想像,程序本身沒有轉換柱子位置,編程完全按照標號(one two three)來實現的,我這樣寫只是便於理解遞歸過程,不知道是否理解?*/

}
}
void move(char x,char y)
{
printf("%c-->%c\n",x,y);
}
/*move 函數只是起到一個列印步驟的作用,one對應『A』,。。,比如move(one,two),就會列印出A-->B */

上面有些是我自己理解時的一些想法,希望能幫到你,實際你把代碼對照演算法多看幾次就OK了,很容易的,理解了自己都可以寫出來

㈦ 求助 !C語言OJjzxx1076怎麼做,想半天了

這個問題?

1076. 小F的蘋果樹

Description

小F有一顆蘋果樹,如果樹枝有分叉,一定是分2叉(就是說沒有隻有1個兒子的結點)

這棵樹共有N個結點(葉子點或者樹枝分叉點),編號為1-N,樹根編號一定是1。

我們用一根樹枝兩端連接的結點的編號來描述一根樹枝的位置。下面是一顆有4個樹枝的樹

2 5

/

3 4

/

1

現在這顆樹枝條太多了,需要剪枝。但是一些樹枝上長有蘋果。

給定需要保留的樹枝數沖行氏量,求出最多能留住多少蘋果。

Input Format

第1行2個數,N和Q(1≤Q≤N1≤Q≤N,1 < N < 101)。

N表示樹的結點數,Q表示要保留的樹枝數量。接下來N-1行描述樹枝的信息。

每行3個整數,前兩個是它連接的結點的編號。第3個數是這根樹枝上蘋果的數量。

每根樹枝上的蘋果不超過30000個。第1行2個數,N和Q(1≤Q≤N1≤Q≤N,1 < N < 101)。

N表示樹的結點數,Q表示要保留的樹枝數量。接下來N-1行描述樹枝的信息。

這題目就是根據輸入創建樹形結構帶隱(每個結構有2個鏈表指針分別指向2個兒子節點)。

所謂的計算蘋果數量,就是遍歷所有節點(除了根節點),檢查其蘋果數量和其兩個兒子的蘋果數量總和,找出最大的散散Q個節點(可以按照數量和排序),最後把這幾個節點的數量和加在一起就是可以保留的最多蘋果數量。

㈧ 演算法編程:用c語言實現

解決這類問題可以使用 回溯 演算法,代碼如下:

#include<stdio.h>
#include<stdlib.h>

#defineM6//候選數字個數
#defineN5//組合後數字位數

intcheck(intresult[],inti)
{
for(intj=0;j<N;j++)
if(result[j]==i)
return0;

return1;
}

intlist(intnumbers[],intl,intresult[],intcount)
{
if(l>=N){

//將各位數組合成一個數
intnum=0;
for(inti=0;i<N;i++){
num=num*10+numbers[result[i]];
}

//判斷這個數是否能被75整除
if(num%75==0){
printf("%d ",num);
count++;
}

returncount;
}

for(inti=0;i<M;i++){

if(!check(result,i)){
continue;
}

result[l]=i;

count=list(numbers,l+1,result,count);

result[l]=-1;
}

returncount;
}

intmain()
{
intnumbers[M]={1,2,5,7,8,9};
intresult[N]={-1,-1,-1,-1,-1};

intcount=list(numbers,0,result,0);

printf("共有%d個 ",count);

system("pause");
return0;
}

運行結果:

㈨ c語言回溯演算法

if(n==7||a[n+1][i]!=1&&a[n+1][i+1]!=1&&a[n+1][i-1]!=1)
這行的代碼是判斷是否可以放皇後的句子。如果可以就將所在位置置 1 。後面也就是這做孝樣做判斷的。這個程序應當有問題,其中try應當是C語言中一個關鍵字啊,不森禪可以這么用。
就我純春稿的看法:八皇後的問題應當用遞歸加回溯會都到更好的代碼,我寫過,不過也快忘了。

㈩ C語言解決八王後問題:好像是絕妙演算法,卻跑不出來

沒人會幫你改譽春,以後也是這樣滴哪虛含李笑嘿嘿。。

這個八皇後如果回溯剪枝不優化的話,用清華大學劉汝佳的演算法:位處理這樣會很快,一般的應該可以算到n=11,LRJ的演算法可以到n=13?我印象中是這樣的。