日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問 生活随笔!

生活随笔

當前位置: 首頁 > 编程资源 > 编程问答 >内容正文

编程问答

算法设计与分析------蛮力法

發布時間:2023/12/8 编程问答 28 豆豆
生活随笔 收集整理的這篇文章主要介紹了 算法设计与分析------蛮力法 小編覺得挺不錯的,現在分享給大家,幫大家做個參考.

算法設計與分析------蠻力法(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;
    • 鄰接表存儲方法
    typedef struct ANode { int adjvex; //該邊的終點編號int weight; //該邊的權值struct ANode *nextarc; //指向下一條邊的指針 } ArcNode; //邊結點類型 typedef struct Vnode { char data[MAXL]; //頂點其他信息ArcNode *firstarc; //指向第一條邊 } VNode; //鄰接表頭結點類型 typedef VNode AdjList[MAXV]; //AdjList是鄰接表類型 typedef struct { AdjList adjlist; //鄰接表int n,e; //圖中頂點數n和邊數e } ALGraph;

    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}0011
    {2}0102
    {1,2}0113
    {3}1004
    {1,3}1015
    {2,3}1106
    {1,2,3}1117

    對于含有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時的所有解和最佳解。

    物品編號重量價值
    154
    234
    323
    411

    ? 【問題求解】對于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任務2任務3任務4
    19278
    26437
    35818
    47694

    代碼如下:

    #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<<"種兌法"; }

    總結

    以上是生活随笔為你收集整理的算法设计与分析------蛮力法的全部內容,希望文章能夠幫你解決所遇到的問題。

    如果覺得生活随笔網站內容還不錯,歡迎將生活随笔推薦給好友。

    主站蜘蛛池模板: 91一区二区国产 | 黄色不卡视频 | 少妇福利视频 | 亚洲天堂一区在线观看 | 国产精品1234| 日本人体视频 | 国产精品aaaa| 成人免费视频国产免费 | 青娱乐在线免费视频 | 国产欧美久久久久 | av成人动漫| 国产精品久久久免费 | 日韩片在线观看 | 三级三级久久三级久久18 | 成人在线观看国产 | 少妇29p| 青青草免费在线视频 | 色呦呦免费视频 | 强伦轩人妻一区二区电影 | 午夜a级片 | 黄色录像三级 | 男女一级特黄 | 青草久久网 | 欧美日韩999| 色哟哟视频在线观看 | 一区二区乱子伦在线播放 | 久久久www成人免费无遮挡大片 | 中文字幕综合在线 | 午夜色综合 | 免费观看污视频 | 韩国黄色精品 | 永久免费黄色片 | 国产特黄| 国产成人观看 | sesese99| 欧美综合一区二区三区 | 小镇姑娘高清播放视频 | 欧美性猛交xxxⅹ富婆 | 探花视频在线版播放免费观看 | 国产一二在线 | 日韩一区二区在线视频 | 亚洲色成人网站www永久四虎 | 91在线视频观看 | 韩产日产国产欧产 | 波多野结衣先锋影音 | 国产欧美高清 | 国产农村妇女毛片精品久久麻豆 | 日韩成人av电影 | 青娱乐国产视频 | 欧美色图88 | 久操免费在线 | 蜜乳av 懂色av 粉嫩av | 91成人高清 | 亚洲第一av在线 | 精品中文字幕视频 | 精品无码人妻少妇久久久久久 | 牛牛在线 | 97av免费视频 | 成人看片黄a免费看视频 | 久草福利在线视频 | 午夜日韩福利 | 色七七久久 | 无码人妻aⅴ一区二区三区 国产高清一区二区三区四区 | 成人高清视频在线观看 | 天天色天天操天天射 | 丝袜 亚洲 另类 欧美 重口 | 日本黄色视屏 | 福利社午夜 | 午夜高清 | 久久av资源站 | 麻豆乱码国产一区二区三区 | 免费毛片播放 | 天天干,天天爽 | 偷拍亚洲色图 | 综合在线播放 | www九九九 | 谁有免费黄色网址 | av鲁丝一区鲁丝二区鲁丝 | 青娱乐av在线 | 亚洲图片在线观看 | av网站免费大全 | 日韩一区二区a片免费观看 伊人网综合在线 | 性xxx欧美| 国产原创av在线 | www天堂在线 | 欧美另类视频在线观看 | 欧美日韩网 | 日韩精品福利 | 日韩精品电影网 | 成人网视频 | 国产一二在线 | 国产欧美a | 一级做a爱片性色毛片 | 亚洲精品久久夜色撩人男男小说 | 国产色秀 | 在线天堂视频 | 麻豆视频在线观看免费网站黄 | av在线资源播放 | 亚洲人性生活视频 |