1. 程式人生 > >演算法實驗4《回溯法》

演算法實驗4《回溯法》

1. 編寫一個簡單的程式,解決8皇后問題。

#include<iostream>
using namespace std;

bool backtrack(int list[8], int t)
{
	if (t >= 8)return true;
	for (int i = 0; i < 8; i++)
	{
		list[t] = i;
		bool place = true;
		for (int j = 0; j < t; j++)if (list[j] == i || j-t==list[j]-i || j-t==i-list[j])place = false
; if (place && backtrack(list, t+1))return true; continue; } return false; } int main() { int list[8]; for (int i = 0; i < 8; i++)list[i] = 0; backtrack(list, 0); for (int i = 0; i < 8; i++)cout << list[i] << " "; system("pause>nul"); return 0; }

2. 批處理作業排程問題
[問題描述]給定n個作業的集合J=(J1, J2, … , Jn)。每一個作業Ji都有兩項任務需要分別在2臺機器上完成。每一個作業必須先由機器1處理,然後再由機器2處理。作業Ji需要機器j的處理時間為tji,i=1,2, … ,n; j=1,2。
對於一個確定的作業排程,設Fji是作業i在機器j上完成處理的時間。則所有作業在機器2上完成處理的時間和成為該作業排程的完成時間和。 
批處理作業排程問題要求對於給定的n個作業,制定一個最佳的作業排程方案,使其完成時間和達到最小。 
要求輸入: 

1)作業數 2)每個作業完成時間表: 

作業完成時間

機器1

機器2

作業1

2

1

作業2

3

1

作業3

2

要求輸出: 1)最佳完成時間 2)最佳排程方案 
提示:演算法複雜度為O(n!),建議在測試的時候n值不要太大,可以考慮不要超過12。

#include<iostream>
using namespace std;

void backtrack(int *t1, int *t2, int *list1, int *list2, int *list, int &sumTime, int &time,
int t, int n) { if (t >= n) { if (sumTime > time)sumTime = time; return; } for (int i = 0; i < n; i++) //選擇1個作業 { bool place = true; for (int j = 0; j < t; j++)if (list[j] == i)place = false; //判斷這個作業是否可選 if (!place)continue; list[t] = i; if (t)t1[t] = t1[t - 1]; else t1[t] = 0; t1[t] += list1[i]; if (t)t2[t] = (t1[t]>t2[t - 1]) ? t1[t] : t2[t - 1]; //這3行計算t2[i] else t2[t] = t1[t]; t2[t] += list2[i]; time += t2[t]; if (time <= sumTime)backtrack(t1, t2, list1, list2, list, sumTime, time, t + 1, n); time -= t2[t]; } } int main() { int n; cin >> n; int *list1 = new int[n]; //作業在機器1上執行的時間t11-t1n int *list2 = new int[n]; //作業在機器2上執行的時間t21-t2n int *t1 = new int[n]; //作業在機器1上完成的時間F11-F1n int *t2 = new int[n]; //作業在機器2上完成的時間F21-F2n int sumTime = 0; //總時間上界 for (int i = 0; i < n; i++) { cin >> list1[i] >> list2[i]; sumTime += (list1[i] + list2[i])*(i + 1); } int *list = new int[n]; //記錄作業執行的順序 int time = 0; //總時間 backtrack(t1, t2, list1, list2, list, sumTime, time, 0, n); cout << sumTime << endl; system("pause>nul"); return 0; }


3. 數字全排列問題
任意給出從1到N的N個連續的自然數,求出這N個自然數的各種全排列。如N=3時,共有以下6種排列方式:123,132,213,231,312,321。
注意:數字不能重複,N由鍵盤輸入(N<=9)。 

#include<iostream>
using namespace std;

void backtrack(int n,int t,int *list)
{
	if (t >= n)
	{
		for (int i = 0; i < n; i++)cout << list[i]+1 << "  ";
		cout << endl;
	}
	for (int i = 0; i < n; i++)
	{
		bool flag = true;
		for (int j = 0; j < t; j++)if (list[j] == i)flag = false;
		if (flag)
		{
			list[t] = i;
			backtrack(n, t + 1, list);
		}
	}
}

int main()
{
	int n;
	cin >> n;
	int list[9];
	backtrack(n, 0, list);
	system("pause>nul");
	return 0;
}