演算法課作業 回溯法

2021-10-07 12:02:58 字數 4455 閱讀 1732

7-2 子集和問題 (20分)

7-3 馬周遊問題 (60分)

返回主目錄

圖k-著色問題是乙個著名的np完全問題。給定無向圖g=(v,e)和正整數k,問可否用k種顏色為v中的每個結點分配一種顏色,使得不會有兩個相鄰結點具有同一種顏色? 該問題的乙個具體例項可能會有多個解(乙個解就是一種合法的著色方案),要求計算全部解的數目。

輸入格式:

輸入的第一行包含三個整數n(1≤n≤20)、m(0≤m≤n(n−1)/2)和k(1≤k≤n),分別是無向圖的結點數、邊數和可用顏色數。 結點從1到n編號,顏色從1到k編號。隨後m行,每行給出一條邊的兩個端點的編號。題目保證給定的無向圖是簡單圖(即不存在自環和多重邊)。

輸出格式:

輸出一行表示全部解的數目(無解時輸出0即可)。

輸入樣例:

5 7 3

1 22 3

3 44 5

5 11 3

1 4輸出樣例:

6

#include

using namespace std;

int n, m, k;

int ans =0;

//number of results

vector

int>

> table;

vector<

int> colorofpoint;

bool islegal

(int point)

}return true;

}void

kcolor

(int point)

for(

int color =

1; color <= k; color++

) colorofpoint[point]=0

;//無論進入下乙個點還是非合法塗色,都應在這裡清零}}

intmain()

}for

(int i =

1; i <= n; i++

)int tmps, tmpe;

for(

int i =

0; i < m; i++

)kcolor(1

);//從第乙個點開始

cout << ans;

return0;

}

子集和問題是乙個典型的np難度問題。給定乙個正整數集合a=(元素互不相同)和乙個正整數y,問是否存在乙個子集y⊆a,它的元素之和為y? 該問題的乙個具體例項可能會有多個解(乙個解就是乙個元素之和為y的子集y⊆a),要求計算並輸出某個特定的解。

輸入格式:

輸入的第一行包含兩個整數n(1≤n≤20)和y(>0),分別是集合a的元素個數和子集和的目標值,a的元素從1到n編號。 接下來的一行有n個數,表示集合a的n個元素。最後乙個行是乙個正整數t,表示待計算並輸出的第t個解。注意,如果將集合中元素由小到大排序,則問題的所有解有字典序。這裡要求輸出按字典序的第t個解。題目保證集合a的元素互不相同且按照遞增次序輸入。

輸出格式:

輸出佔一行, 表示按字典序的第t個解,解中各個數遞增且兩數之間用一空格隔開。若第t個解不存在,則輸出"no solution!"。

輸入樣例:

6 60

10 20 30 50 60 80

2輸出樣例:

10 50

(這裡所有的解按照字典序依次為、、,第2個解為)

#include

using namespace std;

int n, y, t;

vector<

int> num;

vector boolvec;

vector

> ans;

//本程式的思想是通過用布林向量標註符合y的數字,比如10,20,30的向量就是

//num儲存輸入數字,boolvec用來標註當前的布林向量情況,ans用於儲存符合要求的布林向量

void

getallboolvec

(int index,

int sum)

else

if(sum == y)

/*else */

boolvec[index]=0

;//將之前操作取消,進入右子樹,相當於回溯

sum -

= num[index]

;getallboolvec

(index +

1, sum)

;//與前面呼應從而形成左右子樹(實際上還是陣列資料結構)

}void

output

(vector boolvector)

else}}

}int

main()

cin >> t;

getallboolvec(0

,0);

if(t > ans.

size()

)else

return0;

}

如果在n較大t較大的測試點過不了,我提供乙個sample

輸入:

10 10

1 2 3 4 5 6 7 8 9 10

10輸出:

10

任給大小為n×n(8≤n≤1000)的棋盤, 在棋盤上任意設定馬的初始位置,試快速找出一種馬能跳到每個棋格恰好一次的棋步(要求最後回到初始位置)。注意,棋盤上馬按照跳「日」的規則移動。例如,在8×8的棋盤, 當馬位於第3行第4列的方格時,下一步可以跳到箭頭所指的八個方格之一。

輸入格式:

在一行中給出三個正整數n,a,b,其中n(8≤n≤1000)為棋盤的行列大小, a和b(1≤a,b≤n)分別是馬的初始位置所在方格的行號和列號。

輸出格式:

輸出佔n行,每行含有n個正整數,組成乙個n× n方陣。該方陣的n

​2​​ 個元素由正整數1,2,…,n

​2​​ 組成,其中馬走第i步前所處方格其內對應的數為i(i=1,2,…,n

​2​​ ) (馬在初始位置所處方格內數為1)。

輸入樣例:

8 3 4

輸出樣例:

54 57 44 25 64 59 42 9

45 2 55 58 43 8 63 60

56 53 24 1 26 61 10 41

3 46 19 28 21 12 7 62

52 29 4 23 6 27 40 11

47 18 49 20 13 22 37 34

30 51 16 5 32 35 14 39

17 48 31 50 15 38 33 36

這道題我用自己的方法老是超時失敗,我在網上找到了乙個通過的,但是該**風格實在一言難盡。。所以這裡就貼一下吧。注釋掉的就是能通過的。。網上也有寫成專案形式的解題方法。

更新:目前找到了一種思路,待有時間實現看看。

更新:請參考這篇博文,下面先給出他的**。

#include

#include

#include

#include

using namespace std;

typedef

struct

step;

step step[8]

=,,,

,,,,

};struct nextpos };

int board[

100]

[100];

int m,n;

//棋盤大小

//檢測這個位置是否可以走

bool check

(int x,

int y)

//下一位置有多少種走法

intnextposhassteps

(int x,

int y)

return steps;

}//判斷是否回到起點

bool returnstart

(int x,

int y)

//輸出結果

void

outputresult

(int xstart,

int ystart)

} cout<

}//某一位置距離棋盤中心的距離

intpostomidlength

(int x,

int y)

void

backtrace

(int t,

int x,

int y,

int xstart,

int ystart)

else

}while

(nextposqueue.

size()

)}}void

horserun

(int xstart,

int ystart)

intmain()

作業分配(回溯法)

有n份作業分配給n個人去完成,每人完成乙份作業。假定第i個人完成第j份作業需要花費cij時間,cij 0,1 i,j n。試設計乙個回溯演算法,將n份作業分配給n個人完成,使得總花費時間最短。c 實現 author qinwu created time 2017 4 30 22 45 25 file...

回溯法 批處理作業排程 回溯演算法 批處理作業排程

成為該作業排程的完成時間和。批處理作業排程問題要求對於給定的 n個作業 制定乙個最佳的作業排程方案 使其完成時間和達到最小。批處理作業排程問題的乙個常見例子是在計算機系統中完成一批 n個作業,每個作業都要完成先計算,然 後將計算機結果列印輸出這兩項任務 計算任務由計算機的 處理器完成 列印輸出任務由...

演算法 回溯法

0.0 回溯法核心 go depth begin from go 0 1.0 八皇后問題 問題描述 將八位皇后放在一張8x8的棋盤上,使得即任意兩個皇后都不在同一條橫線,豎線和斜線上,問一共有多少種擺法?暴力窮舉 step 1 先不考慮對稱性和可行性,一共是c 8 64 c tbinom c 648...