算法设计与分析------蛮力法
算法設計與分析------蠻力法(c語言)
- 一、蠻力法(窮舉法 枚舉法)
- 1、定義
- 2、蠻力法使用情況
- 3、蠻力法的優點
- 4、蠻力法的缺點
- 5、采用蠻力法設計算法的2類:
- 6、簡單選擇排序和冒泡排序
- 7、字符串匹配
- 8、求解最大連續子序列和問題
- 解法1:
- 解法2:
- 解法3:
- 9、圖的深度優先和廣度優先遍歷
- 二、案例
- 1、求解冪集問題
- 2、求解0/1背包問題
- 3、求解任務分配問題
- 三、蠻力法實驗
- 1、實驗一 求解迷宮問題
- 解法1:
- 解法2:
- 2、實驗二 求解錢幣兌換問題
一、蠻力法(窮舉法 枚舉法)
1、定義
? 蠻力法是一種簡單直接地解決問題的方法,通常直接基于問題的描述和所涉及的概念定義,找出所有可能的解。
然后選擇其中的一種或多種解,若該解不可行則試探下一種可能的解。
2、蠻力法使用情況
3、蠻力法的優點
4、蠻力法的缺點
5、采用蠻力法設計算法的2類:
6、簡單選擇排序和冒泡排序
【問題描述】對于給定的含有n個元素的數組a,對其按元素值遞增排序。
1. 簡單選擇排序
例如,i=3的一趟簡單選擇排序過程,其中a[0…2]是有序的,從a[3…9]中挑選最小元素a[5],將其與a[3]進行交換,從而擴大有序區,減小無序區。
代碼如下:
#include <stdio.h> void swap(int &x,int &y) //交換x和y {int tmp=x;x=y; y=tmp; } void SelectSort(int a[],int n) //對a[0..n-1]元素進行遞增簡單選擇排序 { int i,j,k;for (i=0;i<n-1;i++) //進行n-1趟排序{ k=i; //用k記錄每趟無序區中最小元素的位置for (j=i+1;j<n;j++) //在a[i+1..n-1]中采用窮舉法找最小元素a[k]if (a[j]<a[k]) k=j; if (k!=i) //若a[k]不是最小元素,將a[k]與a[i]交換swap(a[i],a[k]);} } void disp(int a[],int n) //輸出a中所有元素 { int i;for (i=0;i<n;i++)printf("%d ",a[i]);printf("\n"); } int main() { int n=10;int a[]={2,5,1,7,10,6,9,4,3,8};printf("排序前:"); disp(a,n);SelectSort(a,n);printf("排序后:"); disp(a,n); }2. 冒泡排序
例如,i=3的一趟冒泡排序過程,其中a[0…2]是有序的,從a[3…9]中通過交換將最小元素放在a[5]處,從而擴大有序區,減小無序區。
代碼如下:
#include <stdio.h> void swap(int &x,int &y) //交換x和y { int tmp=x;x=y; y=tmp; } void BubbleSort(int a[],int n) //對a[0..n-1]按遞增有序進行冒泡排序 { int i,j;bool exchange;for (i=0;i<n-1;i++) //進行n-1趟排序{ exchange=false; //本趟排序前置exchange為falsefor (j=n-1;j>i;j--) //無序區元素比較,找出最小元素if (a[j]<a[j-1]) //當相鄰元素反序時{ swap(a[j],a[j-1]); //a[j]與a[j-1]進行交換exchange=true;//本趟排序發生交換置exchange為true}if (exchange==false) //本趟未發生交換時結束算法return;} } void disp(int a[],int n) //輸出a中所有元素 { int i;for (i=0;i<n;i++)printf("%d ",a[i]);printf("\n"); } int main() { int n=10;int a[]={2,5,1,7,10,6,9,4,3,8};printf("排序前:"); disp(a,n);BubbleSort(a,n);printf("排序后:"); disp(a,n); }7、字符串匹配
【問題描述】對于字符串s和t,若t是s子串,返回t在s中的位置(t的首字符在s中對應的下標),否則返回-1。
【分析思路】采用直接窮舉法求解,稱為BF算法。該算法從s的每一個字符開始查找,看t是否會出現。例如,s=“aababcde”,t=“abcd”:
代碼如下:
#include <stdio.h> #include <string> using namespace std; int BF(string s,string t) //字符串匹配 {int i=0,j=0;while (i<s.length() && j<t.length()){if (s[i]==t[j]) //比較的兩個字符相同時{i++; j++;}else //比較的兩個字符不相同時{i=i-j+1; //i回退j=0; //j從0開始}}if (j==t.length()) //t的字符比較完畢return i-j; //t是s的子串,返回位置else //t不是s的子串return -1; //返回-1 }int main() {string s="aababcabcde";string t="abcd";printf("index=%d\n",BF(s,t)); }8、求解最大連續子序列和問題
【問題描述】給定一個有n(n≥1)個整數的序列,要求求出其中最大連續子序列的和。
例如:
? 序列(-2,11,-4,13,-5,-2)的最大子序列和為20
? 序列(-6,2,4,-7,5,3,2,-1,6,-9,10,-2)的最大子序列和為16。
規定一個序列最大連續子序列和至少是0(看成0個元素構成的子序列),如果小于0,其結果為0。
解法1:
設含有n個整數的序列a[0…n-1],其中任何連續子序列a[i…j](i≤j,0≤i≤n-1,i≤j≤n-1)求出它的所有元素之和thisSum。
通過比較將最大值存放在maxSum中,最后返回maxSum。
代碼如下:
#include <stdio.h> int maxSubSum1(int a[],int n) //求a的最大連續子序列和 { int i,j,k;int maxSum=0,thisSum; for (i=0;i<n;i++) //兩重循環窮舉所有的連續子序列{ for (j=i;j<n;j++){ thisSum=0;for (k=i;k<=j;k++)thisSum+=a[k];if (thisSum>maxSum) //通過比較求最大連續子序列之和maxSum=thisSum;}}return maxSum; } int main() {int a[]={-2,11,-4,13,-5,-2};int n=sizeof(a)/sizeof(a[0]);int b[]={-6,2,4,-7,5,3,2,-1,6,-9,10,-2};int m=sizeof(b)/sizeof(b[0]);printf("a序列的最大連續子序列的和:%ld\n",maxSubSum1(a,n));printf("b序列的最大連續子序列的和:%ld\n",maxSubSum1(b,m)); }解法2:
? 改進前面的解法,在求兩個相鄰子序列和時,它們之間是關聯的。
? 例如a[0…3]子序列和=a[0]+a[1]+a[2]+a[3],a[0…4]子序列和=a[0]+a[1]+a[2]+a[3]+a[4],在前者計算出來后,求后者時只需在前者基礎上加以a[4]即可,沒有必須每次都重復計算。從而提高了算法效率。
代碼如下:
#include <stdio.h> int maxSubSum2(int a[],int n) //求a的最大連續子序列和 { int i,j;int maxSum=0,thisSum;for (i=0;i<n;i++) { thisSum=0;for (j=i;j<n;j++){ thisSum+=a[j];if (thisSum>maxSum)maxSum=thisSum;}}return maxSum; } int main() {int a[]={-2,11,-4,13,-5,-2};int n=sizeof(a)/sizeof(a[0]);int b[]={-6,2,4,-7,5,3,2,-1,6,-9,10,-2};int m=sizeof(b)/sizeof(b[0]);printf("a序列的最大連續子序列的和:%ld\n",maxSubSum2(a,n)); //輸出:20printf("b序列的最大連續子序列的和:%ld\n",maxSubSum2(b,m)); //輸出:16 }解法3:
? 更一步改進解法2。
如果掃描中遇到負數,當前子序列和thisSum將會減小,若thisSum為負數,表明前面已經掃描的那個子序列可以拋棄了,則放棄這個子序列,重新開始下一個子序列的分析,并置thisSum為0。
若這個子序列和thisSum不斷增加,那么最大子序列和maxSum也不斷增加。
代碼如下:
#include <stdio.h> int maxSubSum3(int a[],int n) //求a的最大連續子序列和 { int i,maxSum=0,thisSum=0;for (i=0;i<n;i++){ thisSum+=a[i];if (thisSum<0) //若當前子序列和為負數,則重新開始下一個子序列thisSum=0;if (maxSum<thisSum) //比較求最大連續子序列和maxSum=thisSum;}return maxSum; } int main() {int a[]={-2,11,-4,13,-5,-2};int n=sizeof(a)/sizeof(a[0]);int b[]={-6,2,4,-7,5,3,2,-1,6,-9,10,-2};int m=sizeof(b)/sizeof(b[0]);printf("a序列的最大連續子序列的和:%ld\n",maxSubSum3(a,n)); //輸出:20printf("b序列的最大連續子序列的和:%ld\n",maxSubSum3(b,m)); //輸出:16 }9、圖的深度優先和廣度優先遍歷
1.圖的存儲結構
- 鄰接矩陣存儲方法
? 鄰接矩陣的類型定義如下:
#define MAXV <最大頂點個數> typedef struct { int no; //頂點編號char data[MAXL]; //頂點其他信息 } VertexType; //頂點類型 typedef struct { int edges[MAXV][MAXV]; //鄰接矩陣的邊數組int n,e; //頂點數,邊數VertexType vexs[MAXV]; //存放頂點信息 } MGraph;- 鄰接表存儲方法
2.深度優先遍歷
從給定圖中任意指定的頂點(稱為初始點)出發,按照某種搜索方法沿著圖的邊訪問圖中的所有頂點,使每個頂點僅被訪問一次,這個過程稱為圖的遍歷。
為了避免同一個頂點被重復訪問,必須記住每個被訪問過的頂點。為此,設置一個訪問標志數組visited[],當頂點i被訪問過時,數組中元素visited[i]置為1;否則置為0。
深度優先搜索的過程是:
(1)從圖中某個初始頂點v出發,首先訪問初始頂點v。
(2)然后選擇一個與頂點v相鄰且沒被訪問過的頂點w為初始頂點,再從w出發進行深度優先搜索。
(3)重復直到圖中與當前頂點v鄰接的所有頂點都被訪問過為止。顯然,這個搜索過程是個遞歸過程。
3.廣度優先遍歷
廣度優先搜索的過程是:
(1)首先訪問初始頂點v。
(2)接著訪問頂點v的所有未被訪問過的鄰接點v1,v2,…,vt。
(3)然后再按照v1,v2,…,vt的次序,訪問每一個頂點的所有未被訪問過的鄰接點,依次類推,直到圖中所有和初始頂點v有路徑相通的頂點都被訪問過為止。
二、案例
1、求解冪集問題
【問題描述】對于給定的正整數n(n≥1),求1~n構成的集合的所有子集(冪集)。
解法1:采用直接蠻力法求解,將1~n的存放在數組a中,求解問題變為構造集合a的所有子集。設集合a[0…2]={1,2,3},其所有子集對應的二進制位及其十進制數如下。
| {} | — | — |
| {1} | 001 | 1 |
| {2} | 010 | 2 |
| {1,2} | 011 | 3 |
| {3} | 100 | 4 |
| {1,3} | 101 | 5 |
| {2,3} | 110 | 6 |
| {1,2,3} | 111 | 7 |
對于含有n(n≥1)個元素的集合a,求冪集的過程如下:
for (i=0;i<2n;i++) //窮舉a的所有子集并輸出 { 將i轉換為二進制數b;輸出b中為1的位對應的a元素構成一個子集; }顯然該算法的時間復雜度為O(n×2n),屬于指數級的算法。
代碼如下:
#include <stdio.h> #include <math.h> #define MaxN 10 void inc(int b[], int n) //將b表示的二進制數增1 { for(int i=0;i<n;i++) //遍歷數組b{ if(b[i]) //將元素1改為0b[i]=0;else //將元素0改為1并退出for循環{ b[i]=1;break;}} } void PSet(int a[],int b[],int n) //求冪集 { int i,k;int pw=(int)pow(2,n); //求2^nprintf("1~%d的冪集:\n ",n);for(i=0;i<pw;i++) //執行2^n次{ printf("{ ");for (k=0;k<n;k++) //執行n次if(b[k])printf("%d ",a[k]);printf("} ");inc(b,n); //b表示的二進制數增1}printf("\n"); } int main() { int n=3;int a[MaxN],b[MaxN];for (int i=0;i<n;i++){ a[i]=i+1; //a初始化為{1,2,3}b[i]=0; //b初始化為{0,0,0}}PSet(a,b,n); }解法2:采用增量蠻力法求解1~n的冪集,當n=3時的求解過程。
這種思路也是蠻力法方法:即窮舉1~n的所有子集。先建立一個空子集,對于i(1≤i≤n),每次都是在前面已建立的子集上添加元素i而構成若干個子集,對應的過程如下:
void f(int n) //求1~n的冪集ps { 置ps={{}}; //在ps中加入一個空子集元素for (i=1;i<=n;i++)在ps的每個元素中添加i而構成一個新子集; }在實現算法時,用一個vector容器表示一個集合元素,用vector<vector >容器存放冪集(即集合的集合)。
代碼如下:
#include <stdio.h> #include <vector> using namespace std; vector<vector<int> > ps; //存放冪集 void PSet(int n) //求1~n的冪集ps {vector<vector<int> > ps1; //子冪集vector<vector<int> >::iterator it; //冪集迭代器vector<int> s,s1;ps.push_back(s); //添加{}for (int i=1;i<=n;i++) //循環添加1~n{ps1=ps;for (it=ps1.begin();it!=ps1.end();++it)(*it).push_back(i); //在ps1的每個集合元素末尾添加ifor (it=ps1.begin();it!=ps1.end();++it)ps.push_back(*it); //將ps1的每個集合元素添加到ps中} } void dispps() //輸出冪集ps {vector<vector<int> >::iterator it; //冪集迭代器vector<int>::iterator sit; //冪集集合元素迭代器for (it=ps.begin();it!=ps.end();++it){printf("{ ");for (sit=(*it).begin();sit!=(*it).end();++sit)printf("%d ",*sit);printf("} ");}printf("\n"); } int main() { int n=3;PSet(n);printf("1~%d的冪集:\n ",n);dispps(); }算法分析:對于給定的n,每一個集合元素都要處理,有2n個,所以上述算法的時間復雜度為O(2n)。
2、求解0/1背包問題
? 【問題描述】有n個重量分別為{w1,w2,…,wn}的物品,它們的價值分別為{v1,v2,…,vn},給定一個容量為W的背包。設計從這些物品中選取一部分物品放入該背包的方案,每個物品要么選中要么不選中,要求選中的物品不僅能夠放到背包中,而且具有最大的價值。
并對下表所示的4個物品求出W=6時的所有解和最佳解。
| 1 | 5 | 4 |
| 2 | 3 | 4 |
| 3 | 2 | 3 |
| 4 | 1 | 1 |
? 【問題求解】對于n個物品、容量為W的背包問題,采用前面求冪集的方法求出所有的物品組合。
對于每一種組合,計算其總重量sumw和總價值sumv,當sumw小于等于W時,該組合是一種解,并通過比較將最佳方案保存在maxsumw和maxsumv中,最后輸出所有的解和最佳解。
#include <stdio.h> #include <vector> using namespace std; vector<vector<int> > ps; //存放冪集 void PSet(int n) //求1~n的冪集ps { vector<vector<int> > ps1; //子冪集vector<vector<int> >::iterator it;//冪集迭代器vector<int> s;ps.push_back(s); //添加{}空集合元素for (int i=1;i<=n;i++) //循環添加1~n{ ps1=ps; //ps1存放上一步得到的冪集for (it=ps1.begin();it!=ps1.end();++it)(*it).push_back(i); //在ps1的每個集合元素末尾添加ifor (it=ps1.begin();it!=ps1.end();++it)ps.push_back(*it); //將ps1的每個集合元素添加到ps中} } void Knap(int w[],int v[],int W) //求所有的方案和最佳方案 { int count=0; //方案編號int sumw,sumv; //當前方案的總重量和總價值int maxi,maxsumw=0,maxsumv=0; //最佳方案的編號、總重量和總價值vector<vector<int> >::iterator it; //冪集迭代器vector<int>::iterator sit; //冪集集合元素迭代器printf(" 序號\t選中物品\t總重量\t總價值\t能否裝入\n");for (it=ps.begin();it!=ps.end();++it) //掃描ps中每一個集合元素{ printf(" %d\t",count+1);sumw=sumv=0;printf("{");for (sit=(*it).begin();sit!=(*it).end();++sit){ printf("%d ",*sit);sumw+=w[*sit-1]; //w數組下標從0開始sumv+=v[*sit-1]; //v數組下標從0開始} printf("}\t\t%d\t%d ",sumw,sumv);if (sumw<=W){ printf("能\n");if (sumv>maxsumv) //比較求最優方案{ maxsumw=sumw;maxsumv=sumv;maxi=count;}}else printf("否\n");count++; //方案編號增加1}printf("最佳方案為: ");printf("選中物品");printf("{ ");for (sit=ps[maxi].begin();sit!=ps[maxi].end();++sit)printf("%d ",*sit);printf("},");printf("總重量:%d,總價值:%d\n",maxsumw,maxsumv); } int main() { int n=4,W=6;int w[]={5,3,2,1};int v[]={4,4,3,1};PSet(n);printf("0/1背包的求解方案\n",n);Knap(w,v,W); }3、求解任務分配問題
【問題描述】有n(n≥1)個任務需要分配給n個人執行,每個任務只能分配給一個人,每個人只能執行一個任務。
第i個人執行第j個任務的成本是ci(1≤i,j≤n)。求出總成本最小的分配方案。
【問題求解】所謂一種分配方案就是由第i個人執行第j個任務,用(a1,a2,…,an)表示,即第1個人執行第a1個任務,第2個人執行第a2個任務,以此類推。全部的分配方案恰好是1~n的全排列。
這里采用增量窮舉法求出所有的分配方案ps(全排列),再計算出每種方案的成本,比較求出最小成本的方案,即最優方案。以n=4,成本如下表所示為例討論。
| 1 | 9 | 2 | 7 | 8 |
| 2 | 6 | 4 | 3 | 7 |
| 3 | 5 | 8 | 1 | 8 |
| 4 | 7 | 6 | 9 | 4 |
代碼如下:
#include <stdio.h> #include <vector> using namespace std; #define INF 99999 //最大成本值 #define MAXN 21 //問題表示 int n=4; int c[MAXN][MAXN]={ {9,2,7,8},{6,4,3,7},{5,8,1,8},{7,6,9,4} }; vector<vector<int> > ps; //存放全排列 void Insert(vector<int> s,int i,vector<vector<int> > &ps1) //在每個集合元素中間插入i得到ps1 { vector<int> s1;vector<int>::iterator it;for (int j=0;j<i;j++) //在s(含i-1個整數)的每個位置插入i{ s1=s;it=s1.begin()+j; //求出插入位置s1.insert(it,i); //插入整數ips1.push_back(s1); //添加到ps1中} } void Perm(int n) //求1~n的所有全排列 { vector<vector<int> > ps1; //臨時存放子排列vector<vector<int> >::iterator it; //全排列迭代器vector<int> s,s1;s.push_back(1);ps.push_back(s); //添加{1}集合元素for (int i=2;i<=n;i++) //循環添加1~n{ ps1.clear(); //ps1存放插入i的結果for (it=ps.begin();it!=ps.end();++it)Insert(*it,i,ps1); //在每個集合元素中間插入i得到ps1ps=ps1;} } void Allocate(int n,int &mini,int &mincost) //求任務分配問題的最優方案 {Perm(n); //求出全排列psfor (int i=0;i<ps.size();i++) //求每個方案的成本{int cost=0;for (int j=0;j<ps[i].size();j++)cost+=c[j][ps[i][j]-1];if (cost<mincost) //比較求最小成本的方案{mincost=cost;mini=i;}} } int main() {int mincost=INF,mini; //mincost為最小成本,mini為ps中最優方案編號Allocate(n,mini,mincost);printf("最優方案:\n");for (int k=0;k<ps[mini].size();k++)printf(" 第%d個人安排任務%d\n",k+1,ps[mini][k]);printf(" 總成本=%d\n",mincost); }三、蠻力法實驗
1、實驗一 求解迷宮問題
【問題描述】有如下8*8的迷宮圖:
OXXXXXXX
OOOOOXXX
XOXXOOOX
XOXXOXXO
XOXXXXXX
XOXXOOOX
XOOOOXOO
XXXXXXXO
其中,O表示通路方塊,X表示障礙方塊。假設入口是位置(0,0),出口為右下角方塊位置(7,7)。設計一個程序采用遞歸方法求指定入口到出口的一條迷宮路徑。
【問題求解】用n表示迷宮大小,二維數組Maze存放迷宮,從(x,y)方塊可以試探上下左右4個方位,假設總是從方位0到方位3的順序試探,各方位對應的水平方向偏移量H[4] = {0,1,0,-1},垂直偏移量V[4] = {-1,0,1,0}。
解法1:
采用深度優先遍歷方式,從(x,y)出發(初始為入口)搜索目標(出口)。
對于當前方塊(x,y):
- 需要試探4個相鄰的方塊。
- 為了避免重復,每走過一個方塊,將對應的迷宮值由’O’改為’ ‘(空字符),當回過來時將其迷宮值恢復為’O’。
代碼如下:
#include <stdio.h> #define MAxN 10 //最大迷宮大小 int n=8; //迷宮大小 char Maze[MAxN][MAxN]= { {'O','X','X','X','X','X','X','X'},{'O','O','O','O','O','X','X','X'},{'X','O','X','X','O','O','O','X'},{'X','O','X','X','O','X','X','O'},{'X','O','X','X','X','X','X','X'},{'X','O','X','X','O','O','O','X'},{'X','O','O','O','O','X','O','O'},{'X','X','X','X','X','X','X','O'} }; int H[4] = {0, 1, 0, -1}; //水平偏移量,下標對應方位號0~3 int V[4] = {-1, 0, 1, 0}; //垂直偏移量 void disppath() //輸出一條迷宮路徑 {for (int i=0; i<n;i++){printf(" ");for(int j=0; j<n;j++)printf("%c",Maze[i][j]);printf("\n");} } void DFS(int x,int y) //求從(x,y)出發的一條迷宮路徑 {if (x==n-1 && y==n-1) //找到一條路徑,輸出{Maze[n-1][n-1]=' ';disppath();return;}else{ for (int k=0;k<4;k++) //試探每一個方位if(x>=0 && y>=0 && x<n && y<n && Maze[x][y]=='O'){ //若(x,y)方塊的可走的Maze[x][y]=' '; //將該方塊設置為空字符DFS(x+V[k],y+H[k]); //查找(x,y)周圍的每一個相鄰方塊Maze[x][y]='O'; //若從該相鄰方塊出發沒有找到路徑,恢復(x,y)}} } int main() {int x=0,y=0; //指定入口,出口默認為(n-1,n-1)printf("一條迷宮路徑:\n");DFS(x,y); //求(0,0)->(7,7)的一條迷宮路徑 }解法2:
? 采用廣度優先遍歷方式,從(x,y)出發(初始為入口)搜索目標(出口)。由于STL中queue不能順序遍歷,這里采用一個數組作為非循環隊列,front和rear分別為隊頭和隊尾(初始時均設置為-1),每個進隊元素有唯一的下標。
隊列元素類型聲明如下:
struct Position //隊列元素類型 { int x,y; //當前方塊位置int pre; //前驅方塊的下標 };首先將根入口方塊(其pre置為-1)進隊,隊列不空循環:
出隊方塊p1作為當前方塊(在隊列數組中的下標為front):
- 若為p1出口:通過隊列數組qu反向推出迷宮路徑并輸出。
- 否則:查找p1的每一個相鄰方塊p2,若p2位置有效(即p2.x>=0 && p2.y>=0 && p2.x<n && p2.y<n)并且可走(Mazep2.x=‘O’),則置p2.pre=front(表示p2的前驅方塊是p1)并將p2方塊進隊。
代碼如下:
#include <stdio.h> #define MAXQ 100 //隊列大小 #define MAxN 10 //最大迷宮大小 int n=8; //迷宮大小 char Maze[MAxN][MAxN]= { {'O','X','X','X','X','X','X','X'},{'O','O','O','O','O','X','X','X'},{'X','O','X','X','O','O','O','X'},{'X','O','X','X','O','X','X','O'},{'X','O','X','X','X','X','X','X'},{'X','O','X','X','O','O','O','X'},{'X','O','O','O','O','X','O','O'},{'X','X','X','X','X','X','X','O'} }; int H[4] = {0, 1, 0, -1}; //水平偏移量,下標對應方位號0~3 int V[4] = {-1, 0, 1, 0}; //垂直偏移量 struct Position //隊列元素類型 {int x,y; //當前方塊位置int pre; //前驅方塊的下標 }; Position qu[MAXQ]; //定義一個隊列qu int front=-1,rear=-1; //定義隊頭和隊尾void disppath(int front) //輸出一條迷宮路徑 {int i,j;for (i=0; i<n;i++) //將所有'*'改為'O'for (j=0;j<n;j++)if (Maze[i][j]=='*')Maze[i][j]='O';int k=front;while (k!=-1) //即路徑上的方塊改為' '{Maze[qu[k].x][qu[k].y]=' ';k=qu[k].pre;}for (i=0; i<n;i++) //輸出迷宮路徑{ printf(" ");for(int j=0; j<n;j++)printf("%c",Maze[i][j]);printf("\n");} } void BFS(int x,int y) //求從(x,y)出發的一條迷宮路徑 {Position p,p1,p2;p.x=x; p.y=y; p.pre=-1; //建立入口結點Maze[p.x][p.y]='*'; //改為'*'避免重復查找rear++; qu[rear]=p; //入口方塊進隊while (front!=rear) //隊不空循環{front++; p1=qu[front]; //出隊方塊p1;if (p1.x==n-1 && p1.y==n-1) //找到出口{disppath(front); //輸出路徑return;}for (int k=0;k<4;k++) //試探p1的每個相鄰方位{p2.x=p1.x+V[k]; //找到p1的相鄰方塊p2p2.y=p1.y+H[k];if (p2.x>=0 && p2.y>=0 && p2.x<n && p2.y<n && Maze[p2.x][p2.y]=='O'){ //方塊p2有效并且可走Maze[p2.x][p2.y]='*'; //改為'*'避免重復查找p2.pre=front;rear++; qu[rear]=p2; //方塊p2進隊}}} } int main() {int x=0,y=0; //指定入口,出口默認為(n-1,n-1)printf("一條迷宮路徑:\n");BFS(x,y); //求(0,0)->(7,7)的一條迷宮路徑 }2、實驗二 求解錢幣兌換問題
【問題描述】某個國家僅有1分.2分和5分硬幣,將錢n(n≥5)兌換成硬幣有很多種兌法。編寫一個實驗程序計算出10分錢有多少種兌法,并列出每種兌換方式。
#include<iostream> using namespace std; int main() {int i,j,k,sum=0;for(i=0;i<100;i++)for(j=0;j<50;j++)for(k=0;k<20;k++){if(i+2*j+k*5==10){ sum=sum+1;cout<<"兌法"<<sum<<";一分錢硬幣"<<i<<"個,二分錢硬幣 "<<j<<"個,五分錢硬幣 "<<k<<"個"<<endl;}}cout<<"共有"<<sum<<"種兌法"; }總結
以上是生活随笔為你收集整理的算法设计与分析------蛮力法的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 字节等单位与进制转换
- 下一篇: Linux 搭建Owncloud 私有云