最基礎的“窮竭搜索”
阿新 • • 發佈:2018-08-02
desc 容易 img rate between 左右 span while align
棧(Stack)
1 #include <stack> 2 #include <cstdio> 3 4 using namespace std; 5 6 int main(int argc, char * argv[]) 7 { 8 stack<int> s; 9 s.push(1); 10 s.push(2); 11 s.push(3); 12 printf("%d\n",s.size()); 13 printf("%d\n",s.empty()); 14 printf("%d\n",s.top()); 15 s.pop(); 16 printf("%d\n",s.top()); 17 s.pop(); 18 printf("%d\n",s.top());//stack非空 19 s.pop(); 20 printf("%d\n",s.size()); 21 printf("%d\n",s.empty()); 22 return 0; 23 }
隊列(Queue)
1 #include <queue> 2 #include <cstdio> 3 4 usingnamespace std; 5 6 int main(int argc, char * argv[]) 7 { 8 queue<int> que; 9 que.push(1); 10 que.push(2); 11 que.push(3); 12 printf("%d\n",que.size()); 13 printf("%d\n",que.front()); 14 printf("%d\n",que.back()); 15 que.pop(); 16 printf("%d\n",que.size());17 printf("%d\n",que.front()); 18 printf("%d\n",que.back()); 19 que.pop(); 20 printf("%d\n",que.size()); 21 printf("%d\n",que.front()); 22 printf("%d\n",que.back()); 23 que.pop(); 24 printf("%d\n",que.size()); 25 printf("%d\n",que.front());//隊列為空,返回值是不確定的 26 printf("%d\n",que.back());//隊列為空,返回值是不確定的 27 printf("%d\n",que.empty()); 28 }
部分和問題
- 題目大意:給定整數a1,a2,…,an,判斷是否可以從中選出若幹數,使它們的和恰好為k
- 限制條件:
- 1≤n≤20
- -108≤ai≤108
- -108≤k≤108
- 題解:深度優先搜索,從a1開始按順序決定每個數加或不加,在全部n個數都決定後在判斷它們的和是不是k即可。因為狀態數是2n,所以復雜度是O(2n)。
- 代碼:
1 #include <iostream> 2 3 using namespace std; 4 5 bool dfs(int, int); 6 7 int n,k; 8 int * a; 9 10 int main() 11 { 12 cin >> n >> k; 13 a = new int[n]; 14 for (int i=0; i<n; i++) 15 { 16 cin >> a[i]; 17 } 18 bool f=dfs(0,0); 19 if (f) cout << "Yes!\n"; 20 else cout << "No!\n"; 21 } 22 23 bool dfs(int i, int s)//已經從前n項得到了和s 24 { 25 if (i==n) return s==k;//如果前n項都已經計算過了,返回s與k是否相等 26 if (dfs(i+1,s)) return true;// 不加上a[i]的情況 27 if (dfs(i+1,s+a[i])) return true;//加上a[i]的情況 28 return false;//無論是否加上a[i]都不能湊成k就返回false 29 }
部分和問題
Lake Counting(POJ 2386)
- 原題如下:
Lake Counting
Time Limit: 1000MS Memory Limit: 65536K Total Submissions: 44746 Accepted: 22116 Description
Due to recent rains, water has pooled in various places in Farmer John‘s field, which is represented by a rectangle of N x M (1 <= N <= 100; 1 <= M <= 100) squares. Each square contains either water (‘W‘) or dry land (‘.‘). Farmer John would like to figure out how many ponds have formed in his field. A pond is a connected set of squares with water in them, where a square is considered adjacent to all eight of its neighbors.
Given a diagram of Farmer John‘s field, determine how many ponds he has.Input
* Line 1: Two space-separated integers: N and M
* Lines 2..N+1: M characters per line representing one row of Farmer John‘s field. Each character is either ‘W‘ or ‘.‘. The characters do not have spaces between them.Output
* Line 1: The number of ponds in Farmer John‘s field.Sample Input
10 12 W........WW. .WWW.....WWW ....WW...WW. .........WW. .........W.. ..W......W.. .W.W.....WW. W.W.W.....W. .W.W......W. ..W.......W.
Sample Output
3
Hint
OUTPUT DETAILS:
There are three ponds: one in the upper left, one in the lower left,and one along the right side. - 題解:從任意的‘W‘開始,不停地把鄰接的部分用‘.‘代替,1次dfs後與初始的這個W連接的所有‘W‘就都被替換成了‘.‘,因此直到圖中不再存在w為止,總共進行dfs的次數就是答案了,復雜度是O(8*n*m)=O(m*n)
- 代碼:
1 #include <iostream> 2 3 using namespace std; 4 5 int n,m; 6 char ** a; 7 8 void dfs(int, int); 9 10 int main() 11 { 12 cin >> n >> m; 13 a = new char*[n]; 14 for (int i=0; i<n; i++) a[i]=new char[m]; 15 for (int i=0; i<n; i++) 16 { 17 for (int j=0; j<m; j++) 18 { 19 cin >> j[i[a]]; 20 } 21 } 22 int s=0; 23 for (int i=0; i<n; i++) 24 { 25 for (int j=0; j<m; j++) 26 { 27 if (j[i[a]]==‘W‘) 28 { 29 dfs(i,j); 30 ++s; 31 } 32 } 33 } 34 cout << s << endl; 35 } 36 37 void dfs(int x, int y) 38 { 39 y[x[a]] =‘.‘; 40 for (int dx=-1; dx<=1; dx++) 41 { 42 for (int dy=-1; dy<=1; dy++) 43 { 44 int xx=x+dx, yy=y+dy; 45 if (xx>=0 && xx<n && yy>=0 && yy<m && yy[xx[a]]==‘W‘) dfs(xx,yy); 46 } 47 } 48 }
Lake Counting
迷宮的最短路徑
- 題目大意:給定一個大小為N*M的迷宮,迷宮由通道和墻壁組成,每一步可以向鄰接的上下左右四格的通道移動,要求出從起點到終點所需的最小步數。假定從起點一定可以移動到終點。
- 限制條件:N,M≤100
- 題解:寬度優先搜索按照距開始狀態由近及遠的順序進行搜索(只要將已經訪問的狀態用標記管理起來),因此可以很容易地用來求最短路徑、最少操作之類問題的答案。這個問題中狀態僅僅是目前所在位置的坐標,因此可以構造成pair或者編碼成int來表達狀態。當狀態更加復雜時,就需要封裝成一個類來表示狀態了。復雜度是O(4*n*m)=O(n*m)
- 代碼:
1 #include <iostream> 2 #include <queue> 3 using namespace std; 4 typedef pair<int,int> P; 5 6 const int INF=100000000; 7 const int MAX_N=100; 8 const int MAX_M=100; 9 char maze[MAX_N][MAX_M+1]; 10 int n,m; 11 int sx=0,sy=1; 12 int tx=9,ty=8; 13 const int dx[4]{-1,0,0,1}; 14 const int dy[4]{0,1,-1,0}; 15 int d[MAX_N][MAX_M]; 16 17 int bfs(); 18 19 int main() 20 { 21 cin >> n >> m; 22 for (int i=0; i<n; i++) 23 for (int j=0; j<m; j++) 24 cin >> j[i[maze]]; 25 cout << bfs(); 26 } 27 28 int bfs() 29 { 30 queue<P> que; 31 for (int i=0; i<n; i++) 32 for (int j=0; j<n; j++) 33 j[i[d]]=INF; 34 que.push(P(sx,sy)); 35 sy[sx[d]]=0; 36 while (que.size()) 37 { 38 P p=que.front(); 39 que.pop(); 40 if (p.first==tx && p.second==ty) break; 41 for (int i=0; i<4; i++) 42 { 43 int xx=p.first+dx[i]; 44 int yy=p.second+dy[i]; 45 if (xx>=0 && xx<n && yy>=0 && yy<m && yy[xx[maze]]!=‘#‘ && yy[xx[d]]==INF) 46 { 47 que.push(P(xx,yy)); 48 yy[xx[d]]=p.second[p.first[d]]+1; 49 } 50 } 51 } 52 return ty[tx[d]]; 53 }
迷宮的最短路徑
特殊狀態的枚舉
雖然生成可行解空間多數采用深度優先搜索,但在狀態空間比較特殊時其實可以很簡短地實現
如,C++標準庫中提供了next_permutation函數,可以把n個元素共n!種不同的排列生成出來
又如,通過位運算,可以枚舉n個元素中取出k個的共C(n,k)種狀態或是某個集合中的全部子集等
貼一段書上的代碼:
1 bool used[MAX_N]; 2 int perm[MAX_N]; 3 4 void permutation1(int pos, int n) 5 { 6 if (pos==n) 7 { 8 /* 9 *這裏編寫需要對perm進行的操作 10 */ 11 return ; 12 } 13 for (int i=0; i<n; i++) 14 if (!used[i]) 15 { 16 perm[pos]=i; 17 used[i]=true; 18 permutation1(pos+1,n); 19 used[i]=false; 20 } 21 return ; 22 } 23 _______________________________________________ 24 #include <algorithm> 25 //即使有重復的元素也會生成所有的排列 26 //next_permutation是按照字典序來生成下一個排列的 27 int perm2[MAX_N]; 28 void permutation2(int n) 29 { 30 for (int i; i<n; i++) perm2[i]=i; 31 do 32 { 33 /* 34 *這裏編寫需要對perm2進行的操作 35 */ 36 } 37 while (next_permutation(perm2, perm+n)); 38 //所有的排列都生成後,next_permutation會返回false 39 return ; 40 }
最基礎的“窮竭搜索”