C++算法學習之回溯法的應用_第1頁
C++算法學習之回溯法的應用_第2頁
C++算法學習之回溯法的應用_第3頁
C++算法學習之回溯法的應用_第4頁
C++算法學習之回溯法的應用_第5頁
已閱讀5頁,還剩3頁未讀 繼續免費閱讀

下載本文檔

版權說明:本文檔由用戶提供并上傳,收益歸屬內容提供方,若內容存在侵權,請進行舉報或認領

文檔簡介

第C++算法學習之回溯法的應用for(inti=1;ii++){

a[t][i]=1-(a[t+1][i]+a[t+1][i+1])%2;//遞推第t層i列的符號

if(a[t][i])//若為+

sum2++;

if(2*(sum1+sum2)==(n*(n+1)/2))//記錄+總數是否為符號總數的一半

sum++;

voiddfs(intx){//x表示考慮頂層第x個位置的符號

for(inti=0;ii++){

//0=1=+

if(i)

sum1++;//記錄頂層+的數量

a[n][x]=i;

if(x==n)//考慮完頂層的一種符號擺放,進行檢查

check();

else

dfs(x+1);

if(i)

sum1--;//若上擺放為+,則+數量回退1

intmain()

cinn;

if((n*(n+1)/2)%2==1)//判斷符號總數奇偶性

cout0endl;

else{

dfs(1);

coutsumendl;

return0;

算法分析與知識點:

本題主要運用回溯的思想,這題的特點是不能輸入元素,而且只要確定的頂層的n的符號的排列情況,就可以得到整個符號三角形的排列情況,因此只需要對符號三角形的頂層進行遍歷就好了。題目中有要求+和-的數量要一樣,所以符號三角形的符號總數要是偶數,否則解決方案數為0。

令0和1分別代表-和+,其他層在頂層確定后即確定了,不需要枚舉。采用dfs對第一層的符號排列情況進行遍歷,遍歷完n后就可得到答案。

回溯堂練

實驗題目:森林迷宮

題目描述:

一天Luna在森林里探險的時候不小心走入了一個迷宮,迷宮可以看成是由n*n的格點組成,每個格點只有2種狀態:^和#;前者表示可以通行后者表示不能通行。當Luna處在某個格點時,她只能移動到東南西北(或者說上下左右)四個方向之一的相鄰格點上,Luna想要從起點A走到終點B(中途不能走出迷宮)。如果起點或者終點有一個不能通行(為#),則當做無法通行。

輸入要求:

第1行是測試數據的組數k,后面跟著k組輸入。

每組測試數據的第1行是一個正整數n(1=n=100),表示迷宮的規模是n*n的。

接下來是一個n*n的矩陣,矩陣中的元素為.或者#。

再接下來一行是4個整數ar,ac,br,bc。表示A處在第ar行,第ac列,B處在第br行,第bc列。注意坐標ar,ac,br,bc全部是從0開始計數的類似[1,4][5,6]被認為是覆蓋了[1,6]。

輸出要求:

YES或NO

實驗代碼及注釋:

#includebits/stdc++.h

usingnamespacestd;

chars[105][105];//記錄地圖

intn,ha,la,hb,lb,dir[4][2]={{0,-1},{0,1},{-1,0},{1,0}},flag;//flag標記搜索完畢后是否能到達終點

voiddfs(intha,intla)

if(ha==hbla==lb)//判斷是否達到終點

flag=1;

if(flag){

cout"YES"endl;

return;

for(inti=0;ii++)

intdx=ha+dir[i][0];

intdy=la+dir[i][1];

if(dx=0dxndy=0dyns[dx][dy]=='^')

s[dx][dy]='#';//只走一次,每個方都要走一遍,只要連通,肯定能到終點

dfs(dx,dy);

intmain()

intk;

cink;

while(k--)

cinn;

for(inti=0;ii++)for(intj=0;jj++)cins[i][j];

cinhalahblb;

if(s[ha][la]=='#'||s[hb][lb]=='#')cout"NO"endl;//提前判斷始點和終點是否符合要求

else

flag=0;

dfs(ha,la);//dfs搜索路徑

if(flag==0)cout"NO"endl;

return0;

算法分析與知識點:

本采用深度優先的搜索方式來搜索全部路徑,大致思路為:從當前點出發,往四個方位探尋找出所有與之相鄰的且尚未被訪問過的點,從中暫時先選取一個點作為當前點繼續上述過程,直到到達目的地或者再也無法探尋到能前進的點,再返回。如果當前搜索的點到達了目標點,flag標記為true,返回即可。若所有能到達的點都搜索完了,flag仍為false,則無法到達。

實驗題目:地圖著色

題目描述:

給定圖G=(V,E),需要為圖G的各頂點著色,是否有一種著色法使G中相鄰的兩個頂點有不同的顏色

輸入要求:

第一行是頂點的個數n(2n10),顏色數m(1mn)。

接下來是頂點之間的連接關系:ab;表示a和b相鄰。頂點從1開始計。

當a,b同時為0時表示輸入結束。

輸出要求:

輸出著色方案總數和最少顏色數。如果無可行方案,顏色數為0。

實驗代碼及注釋:

#includebits/stdc++.h

usingnamespacestd;

#defineN10

intn,sum=0,m;

intx[N+1];//記錄可行解

intg[N+1][N+1];//鄰接矩陣

intans=N;

intok(intt)//判斷當前層節點是否可行

for(intj=1;jj++)

if(g[t][j]==1x[t]==x[j])

return0;

return1;

intnum_m(){//計算可行解中的顏色種類數

intans=0;

inttemp[101]={0};

for(inti=1;ii++){

temp[x[i]]=1;

for(inti=1;i=100;i++)

ans+=temp[i];

returnans;

voidback_track(intt)

inti;

if(tn)

sum++;//找到可行解,總數+1

//for(i=1;ii++)

//printf("%d",x[i]);

//printf("\n");

intxx=num_m();

if(xxans)

ans=xx;

else

for(inti=1;ii++)//遍歷節點的每種顏色取值

x[t]=i;

if(ok(t))

back_track(t+1);

x[t]=0;

intmain()

cinnm;//n個頂點,m種顏色

inta,b;

cinab;

while(!(a==0b==0)){//構造鄰接矩陣

g[a][b]=1;

g[b][a]=1;

cinab;

back_track(1);

if(sum)

coutsum""ansendl;

else

cout0""0endl;

return0;

算法分析與知識點:

這個問題和八皇后還有求子集和等問題都具有類似之處,其核心在通過遍歷找到所有的問題子集,但是在遞歸遍歷的時候,都在加一個判斷,將那些明顯不滿足條件的情況給直接排出,減少問題的規模,其實這類問題,在遞歸遍歷的時候都是類似與對一顆樹的便利每個節點相當走到此時的狀態,然后再判斷此時的狀態是否能繼續走下去,如果不能就將其回溯到上一個節點,避免浪費時間。

給定圖g(v,e)和m種顏色,如果這個圖不是m可著色,給出否定回答,是的話找出所有不同著色法。

分析:

用鄰接矩陣表示圖g,如果頂點i跟j之間有邊,則g[i][j]=1,否則g[i][j]=0.用整數1,2,,m表示m種顏色,頂點i的顏色用x[i]表示,所以x[1:n]是一種著色方案。

溫馨提示

  • 1. 本站所有資源如無特殊說明,都需要本地電腦安裝OFFICE2007和PDF閱讀器。圖紙軟件為CAD,CAXA,PROE,UG,SolidWorks等.壓縮文件請下載最新的WinRAR軟件解壓。
  • 2. 本站的文檔不包含任何第三方提供的附件圖紙等,如果需要附件,請聯系上傳者。文件的所有權益歸上傳用戶所有。
  • 3. 本站RAR壓縮包中若帶圖紙,網頁內容里面會有圖紙預覽,若沒有圖紙預覽就沒有圖紙。
  • 4. 未經權益所有人同意不得將文件中的內容挪作商業或盈利用途。
  • 5. 人人文庫網僅提供信息存儲空間,僅對用戶上傳內容的表現方式做保護處理,對用戶上傳分享的文檔內容本身不做任何修改或編輯,并不能對任何下載內容負責。
  • 6. 下載文件中如有侵權或不適當內容,請與我們聯系,我們立即糾正。
  • 7. 本站不保證下載資源的準確性、安全性和完整性, 同時也不承擔用戶因使用這些下載資源對自己和他人造成任何形式的傷害或損失。

評論

0/150

提交評論