Review of Algorithmic Design and Analysis Test
Theories
1. Basic concepts and properties of algorithms and their relations and differences with programs
Algorithms: Algorithms refer to a series of calculation steps to solve a problem, which is an accurate and complete description of the solution.
Basic properties of the algorithm:
- Input: There are zero or more external quantities as input to the algorithm.
- Output: The algorithm produces at least one quantity as output.
- Deterministic: Each instruction that makes up an algorithm must be clear and unambiguous.
- Limited: Limited number of executions and limited execution time of instructions in the algorithm.
- Feasibility: Each operation in the algorithm must be basic enough to be executed accurately.
Program: is the specific implementation of the algorithm in a design language, the program can not satisfy the limitations of the algorithm.
2. Complexity of the algorithm, how to measure it, asymptotic complexity and order of the algorithm
The evaluation of an algorithm is mainly based on the time and space complexity.
Time complexity refers to the time required to execute an algorithm. Spatial complexity refers to the memory space consumed by an algorithm. Generally speaking, the complexity of a computer algorithm is a function f(n) of the problem size n. When the problem size n is large enough, we only need to consider the order of the algorithm complexity in an asymptotic sense.
3. Definition of large O representation and asymptotic time complexity
f(n)=O(g(n)), if and only if there are constants c>0 and n0>0, so that f(n)<=g(n) is always true when n>=n0.
If the scale of a problem is n, the time required for the algorithm to solve the problem is T(n), which is a function of N and is called the time complexity of the algorithm. When n is large enough, the limit state of T(n) is called the asymptotic time complexity of the algorithm.
4. Basic Ideas of Several Algorithms
-
Divide and conquer: Divide the problem with scale n into k smaller subproblems, which are independent of each other and the same as the original problem, solve these subproblems recursively, and then combine the solutions of the subproblems to get the solution of the original problem.
-
Backtrace algorithm: In the solution space tree that contains all the solutions to the original problem, a depth-first search strategy is used to search the solution space tree from the root node. When a node is searched, it is determined whether the node contains the solution of the original problem first, and if it does, it is searched further, otherwise it is backtracked to its ancestor node one by one.
-
Branch and Bound: Searches for solution space trees using a breadth-first search method. Each live node has only one chance to become an extension node. When it becomes an extension node, all the son nodes are generated one time. Among these son nodes, the son nodes that are not feasible or not optimal are discarded, and the rest of the son nodes join the queue at the end of the live node table. After that, take the next node from the queue head of the active node table to become an extended node and repeat the above steps until the optimal solution is found or the active node table is empty.
-
Dynamic programming: The original problem is decomposed into several smaller subproblems, which are solved first, and then the solution of the original problem is obtained by solving the subproblems.
Basic steps:
- Find out the properties of the optimal solution and describe its structural characteristics.
- Recursively define the optimal value;
- Optimal values are calculated from bottom to top.
- The optimal solution is constructed based on the information obtained from the calculation of the optimal solution.
Basic elements: optimal substructure property, no aftereffect and subproblem overlap property.
The optimal substructure property means that the optimal solution of the problem contains the optimal solution of the subproblem.
Invalidity refers to that the process before a certain state does not affect the decision-making of the later state, but only relates to the current state.
The overlapping nature of sub-problems means that a sub-problem may be used many times in the next stage of decision-making. Dynamic programming uses this feature to calculate each sub-problem only once and then save the results in a table, which only needs to be taken out of the table when needed.
-
Greedy algorithm: Greedy algorithm always makes the best choice at present, that is, greedy algorithm is not considered from the overall optimum, the choice is only the local optimum choice in a sense.
Basic steps:
- Start with an initial solution to the problem;
- When the loop statement can be used to further solve the problem, a local optimal solution is obtained according to the local optimal strategy, which reduces the scale of the problem.
- All the local optimal solutions are combined to get the solution of the original problem.
Basic elements: greedy selection, optimal substructure, no aftereffect.
Greedy selectivity means that the overall optimal solution of the problem can be reached by a series of local optimal choices.
-
Memo method: Save the solution of the solved subproblem in a table, solve it recursively from top to bottom, and return the solution of the subproblem directly from the table when it is recursive to the solved subproblem.
5. The Connection and Difference of Several Algorithms
-
Divide and conquer algorithm vs dynamic programming
Linkage: The basic idea is the same, which divides the original problem into several sub-problems, solves the sub-problems first, and then solves the sub-problems to get the solution of the original problem.
Difference: For problems solved by dynamic programming, the subproblems decomposed are often not independent of each other. The subproblems of divide-and-conquer method are calculated repeatedly. Dynamic programming method has a table for the solution of the subproblems, thus avoiding the problem of repeated calculation of the subproblems.
-
Dynamic Planning vs. Memo (Memory Search)
Contact: Use tables to save the answers to the solved sub-questions so as to avoid repeated calculation of the sub-questions
Difference: Dynamic programming recursion is bottom-up, while memo recursion is top-down.
-
Branch and Bound vs Backtrace
Difference: Different extension methods are used for expanded nodes, Branch and Bound uses a breadth-first search, which ends when the search to the optimal solution or the active node table is empty, and Back-off uses a depth-first search, which ends only when all viable children of the active node are traversed.
-
Greedy algorithm vs dynamic programming
Linkage: Both require the problem to have optimal substructural properties and no aftereffect
Difference: In dynamic programming, the choice made at each step often depends on the solution of the related subproblem, so the choice can only be made after the related subproblem is solved, using a bottom-up recursive approach; In the greedy algorithm, only the best choice is made in the current state, that is, the local optimal selection, and then the corresponding sub-problems resulting from making this choice are solved, using a top-down recursive approach.
6. General patterns of some algorithms
-
General pattern of backtracking algorithms
int n,a[N]; //n is the number of objects investigated void backtrack (int m) { if (m>n) output(); //Leaf node, output feasible solution else for(int i=0;i<=k;i++) //All child nodes of the current node { a[m]=value(i); //The value of each child node is assigned to a[m] if (constraint(m)&&bound(m)) //Satisfy constraints and bounds backtrack(m+1); //Recursive Next Layer } }
-
Searching for Subset Trees by Backtracking
int n,a[N]; //n is the number of objects investigated void search(int m) //m is the current object of investigation { if(m>n) //Recursive End Conditions output(); //Corresponding output else for(int i=0;i<=1;i++) //Controls the number of branches, where there are only two branches, 0 and 1 indicating whether the backpack is loaded { a[m]=i; if(constraint(m)&&bound(m)) //Pruning function: Constraint function + Bound function - > Recursion search(m+1); } }
-
Searching permutation trees using backtracking
int n,a[N]; //n is the number of objects examined, a[N] is initialized as one of the permutations void search(int m) //m is the current object of investigation { if(m>n) //Recursive End Conditions output(); //Corresponding output else for (int i=m;i<=n;i++) { swap(a[m],a[i]); //Change Position if (constraint(m)&&bound(m)) //Do not go further if the restriction function is not satisfied search(m+1); swap(a[m],a[i]); //Return to original position } }
-
General pattern of branch and bound method
struct node { int x,y; }e1,e2; vector <node> q; int flag[N][N]; //Mark whether the node has arrived, initialized to 0 void search() { cin>>e1.x>>e1.y; q.push(e1); flag[e1.x][e1.y]=1; //Marker e1 arrived while(!q.empty()) { e2=q.front(); q.pop(); for(For extension nodes e2 Each new node that you get e1) { if(e1 Is Target Node) { output(); return; //Output results and return } if(flag[e1.x][e1.y]==0&&bound(e1)) //Limit condition met and not reached { q.push(e1); flag[e1.x][e1.y]=1; //Marker e1 arrived } } } }
Topic Question
The code shown in the following two lines of space is the core code
1. Binary Search
#include <iostream> using namespace std; const int N=10001; int a[N]; void binarysearch(int l,int r,int x) { if(l>r) { cout<<"No"<<endl; return; } int mid=l+r>>1; if(a[mid]==x) { cout<<"Yes"<<endl; return; } else if(a[mid]>x) binarysearch(l,mid-1); else binarysearch(mid+1,r); return; } int main() { int n,m,x; cin>>n; for(int i=0;i<n;i++) cin>>a[i]; cin>>m; for(int i=0;i<m;i++) { cin>>x; binarysearch(0,n-1,x); } }
2. Merge Sort
#include <iostream> using namespace std; const int N=10010; int a[N]; void Merge(int l,int mid,int r) { int tmp[r-l+1]; int cnt=0,i,j; for(i=l,j=mid+1;i<=mid&&j<=r;) { if(a[i]<a[j]) tmp[cnt++]=a[i++]; else tmp[cnt++]=a[j++]; } while(i<=mid) tmp[cnt++]=a[i++]; while(j<=r) tmp[cnt++]=a[j++]; for(int i=0;i<cnt;i++) a[l+i]=tmp[i]; } void mergesort(int l,int r) { if(l<r) { int mid=r+l>>1; mergesort(l,mid); mergesort(mid+1,r); Merge(l,mid,r); } } int main() { int n; cin>>n; for(int i=0;i<n;i++) cin>>a[i]; mergesort(0,n-1); for(int i=0;i<n;i++) cout<<a[i]<<endl; return 0; }
3.01 Backpack
#include <iostream> #include <cstring> using namespace std; int dp[10000010]; int main() { int n,c; while(cin>>n>>c) { if(n==0&&c==0) break; int w[11],v[11]; for(int i=1;i<=n;i++) cin>>w[i]; for(int i=1;i<=n;i++) cin>>v[i]; memset(dp,0,(c+1)*sizeof(int)); for(int j=1;j<=n;j++) for(int i=c;i>=w[j];i--) //Particular attention dp[i]=max(dp[i],dp[i-w[j]]+v[j]); cout<<dp[c]<<endl; } return 0; }
4.Queens of Eight Queens
#include <iostream> using namespace std; int a[8],cnt,usedcol[8],used1[15],used2[15]; void output() { cnt++; cout<<"No "<<cnt<<':'<<endl; for(int i=0;i<8;i++) { for(int j=0;j<8;j++) { if(j==a[i]) cout<<'A'; else cout<<'.'; } cout<<endl; } } void dfs(int i) { if(i==8) {output();return;} for(int j=0;j<8;j++) { if(!usedcol[j]&&!used1[j+i]&&!used2[j-i+7]) { a[i]=j; usedcol[j]=used1[j+i]=used2[j-i+7]=1; dfs(i+1); usedcol[j]=used1[j+i]=used2[j-i+7]=0; } } return; } int main() { dfs(0); return 0; }
5. Add one times two squares
#include <iostream> #include <queue> using namespace std; struct T { int num,cnt; }e1,e2; queue <T> q; bool flag[10001]; int main() { int m,n; cin>>m>>n; e1.num=m; e1.cnt=0; q.push(e1); flag[e1.num]=true; while(!q.empty()) { e2=q.front(); q.pop(); if(e2.num==n) {cout<<e2.cnt<<endl;break;} else { e1.cnt=e2.cnt+1; e1.num=e2.num+1; if(e1.num<=n&&!flag[e1.num]) { q.push(e1); flag[e1.num]=true; } e1.num=e2.num<<1; if(e1.num<=n&&!flag[e1.num]) { q.push(e1); flag[e1.num]=true; } e1.num=e2.num*e2.num; if(e1.num<=n&&!flag[e1.num]) { q.push(e1); flag[e1.num]=true; } } } }
6. Electronic mice run mazes
#include<iostream> #include<queue> using namespace std; int flag[13][13], ex, ey, dx[] = { -1,1,0,0 }, dy[] = { 0,0,-1,1 }; struct brid { int x, y; int cnt; }e1, e2; queue <brid> m; int main() { cin >> e1.x >> e1.y >> ex >> ey; for (int i = 1; i <= 12; i++) for (int j = 1; j <= 12; j++) { char s; cin >> s; if (s == 'X') flag[i][j] = 1; } m.push(e1); while (!m.empty()) { e2 = m.front(); m.pop(); if (e2.x == ex && e2.y == ey) { break; } else { for (int k = 0; k < 4; k++) { e1.x = e2.x + dx[k]; e1.y = e2.y + dy[k]; if (e1.x >= 1 && e1.x <= 12 && e1.y >= 1 && e1.y <= 12 && !flag[e1.x][e1.y]) { e1.cnt = e2.cnt + 1; m.push(e1); flag[e1.x][e1.y] = 1; } } } } cout << e2.cnt << endl; return 0; }
7. Longest Common Subsequence
#include<iostream> #include<cstring> #include<cmath> using namespace std; string origin, target; int dp[201][201]; int main() { cin >> origin >> target; int len1 = origin.size(); int len2 = target.size(); for (int i = 1; i <= len1; i++) { for (int j = 1; j <= len2; j++) { if (origin[i - 1] == target[j - 1]) dp[i][j] = dp[i - 1][j - 1] + 1; else dp[i][j] = max(dp[i - 1][j], dp[i][j - 1]); } } cout << dp[len1][len2] << endl; }
8. Maximum continuous subsequences and
#include <iostream> using namespace std; int a[1001]; int main() { int n,sum(0); cin>>n; for(int i=0;i<n;i++) cin>>a[i]; int Max=a[0]; for(int i=0;i<n;i++) { sum+=a[i]; if(sum>Max) Max=sum; if(sum<0) sum=0; } cout<<Max<<endl; }
9. Scheduling of activities
#include <iostream> #include <algorithm> using namespace std; struct active { int b,e; }a[1001]; struct rule { bool operator()(const active &a,const active &b) { return a.e<b.e; } }; int main() { int n; cin>>n; for(int i=0;i<n;i++) cin>>a[i].b>>a[i].e; sort(a,a+n,rule()); int r=a[0].e; int ans=1; for(int i=1;i<n;i++) { if(a[i].b>=r) { ans++; r=a[i].e; } } cout<<ans<<endl; return 0; }
10. Round Robin schedule
#include <iostream> #include <cmath> using namespace std; int n,a[130][130]; void Merge (int left,int mid,int right) { int r=right-left+1; r/=2; for(int i=1;i<=r;i++) { for(int j=left;j<=mid;j++) a[i+r][j+r]=a[i][j]; for(int j=mid+1;j<=right;j++) a[i+r][j-r]=a[i][j]; } } void Partition(int left,int right) { if(left<right) { int mid=(right+left)/2; Partition(left,mid); Partition(mid+1,right); Merge(left,mid,right); } } int main() { cin>>n; n--; int num=2<<n; //n-th power of 2 for(int i=1;i<=num;i++) a[1][i]=i; Partition(1,num); for(int i=1;i<=num;i++) { int j; for(j=1;j<num;j++) cout<<a[i][j]<<' '; cout<<a[i][j]<<endl; } return 0; }
11. Calculate Matrix Continuous Product
#include<iostream> #include <cmath> using namespace std; const int N = 11; int row[N], col[N], n, dp[N][N]; int main() { cin >> n; for (int i = 1; i <= n; i++) cin >> row[i] >> col[i]; for(int cnt = 1;cnt<=n;cnt++) for (int i = 1,j=cnt; j <= n; i++,j++) { if (i == j) dp[i][j] = 0; else { dp[i][j] = 100000; for (int k = i; k < j; k++) //k must start with i dp[i][j] = min(dp[i][j], dp[i][k] + dp[k + 1][j] + row[i] * col[k] * col[j]); } } cout << dp[1][n] << endl; return 0; }
12. Quick Sort
#include<iostream> using namespace std; #define maxn 100001 int n, a[maxn]; void quicksort(int l, int r) { if (l >= r) return; int i = l, j = r, mid=l + (r - l >> 1); //Select the middle value as the base point while (i < j) { for (; a[i] < a[mid]; i++); for (; a[j] > a[mid]; j--); if (i < j) swap(a[i], a[j]); //Note here that i<j is to be judged } quicksort(l, i); quicksort(i + 1, r); } int main() { cin >> n; for (int i = 0; i < n; i++) cin >> a[i]; quicksort(0, n - 1); for (int i = 0; i < n; i++) cout << a[i] << ' '; return 0; }
13. Fibonacci number column
//Implementation by memo int result[n]; int fib (int m) { if(m<=2) return 1; if(result[m]!=0) return result[m]; result[m]=fib(m-1)+fib(m-2); return result[m]; } //Implemented by Dynamic Programming int dp[n]; int fib(int m) { if(m<=2) return 1; dp[1]=dp[2]=1; for(int i=3;i<=m;i++) dp[i]=dp[i-1]+dp[i-2]; return dp[m]; }
14. Loading problems
#include<iostream> using namespace std; int sign = 0, n, c1, c2, weigh[100]; void FoundPath(int c1_w, int c2_w, int times) { if (c1_w > c1 || c2_w > c2) return; if (times == n) { sign = 1; return; } FoundPath(c1_w + weigh[times], c2_w, times + 1); FoundPath(c1_w, c2_w + weigh[times], times + 1); return; } int main() { int cnt = 0, c1_w = 0, c2_w = 0, times = 0, ans[100]; while (cin >> c1 >> c2 >> n) { if (n == 0 && c1 == 0 && c2 == 0) break; for (int i = 0; i < n; i++) cin >> weigh[i]; sign = 0, c1_w = 0, c2_w = 0, times = 0; FoundPath(c1_w, c2_w, times); ans[cnt++] = sign; } for (int i = 0; i < cnt; i++) { if (ans[i] == 0) cout << "No" << endl; else cout << "Yes" << endl; } return 0; }
15. m-coloring of Graphs
#include<iostream> #include<vector> using namespace std; int n, m, r, ans; int color[20]; vector <int> b[20]; //Adjacency table stores undirected graph bool check(int v,int k) { for (int i = 0; i < b[v].size(); i++) { int u = b[v][i]; if (color[u] == k) return false; } return true; } void dfs(int v,int c) { color[v] = c; for (int i = 0; i < b[v].size(); i++) { int u = b[v][i]; if (color[u]) continue; for (int k = 1; k <= m; k++) { if (check(u, k)) { dfs(u, k); int j; for (j = 0; j < n; j++) { if (!color[j]) break; } if (j >= n) ans++; color[u] = 0; //Pay special attention to the need to remove markers here } } } } int main() { cin >> n >> r >> m; for (int i = 0; i < r; i++) { int u, v; cin >> u >> v; b[u].push_back(v); b[v].push_back(u); } for(int i=1;i<=m;i++) dfs(0,i); cout << ans << endl; return 0; }
16.8 Digital Issues
#include<iostream> #include<map> #include<cstring> #include<queue> using namespace std; string str; map<string, int> visit; struct Node { string status; int cnt; Node(string s = "", int c = 0) :status(s), cnt(c) {} }; void swap(string& s, int i, int j) { char c = s[i]; s[i] = s[j], s[j] = c; } string Up(string str) { int pos = str.find("0"); if (pos <= 2) return ""; swap(str, pos, pos - 3); return str; } string Down(string str) { int pos = str.find("0"); if (pos >= 6) return ""; swap(str, pos, pos + 3); return str; } string Left(string str) { int pos = str.find("0"); if (pos == 0 || pos == 3 || pos == 6) return ""; swap(str, pos, pos - 1); return str; } string Right(string str) { int pos = str.find("0"); if (pos == 2 || pos == 5 || pos == 8) return ""; swap(str, pos, pos + 1); return str; } int bfs() { visit[str] = 1; queue<Node> Q; Q.push(Node(str)); while (!Q.empty()) { Node cn = Q.front(); Q.pop(); if (cn.status == "123456780") return cn.cnt; string news = Up(cn.status); if (news != "" && visit[news] != 1) { Q.push(Node(news, cn.cnt + 1)); visit[news] = 1; } news = Down(cn.status); if (news != "" && visit[news] != 1) { Q.push(Node(news, cn.cnt + 1)); visit[news] = 1; } news = Left(cn.status); if (news != "" && visit[news] != 1) { Q.push(Node(news, cn.cnt + 1)); visit[news] = 1; } news = Right(cn.status); if (news != "" && visit[news] != 1) { Q.push(Node(news, cn.cnt + 1)); visit[news] = 1; } } return -1; } int main() { string tmp; int n = 9; while (n && cin >> tmp) { str += tmp; n--; } cout << bfs() << endl; return 0; }
17. Optimal Service Order Problem
vector<double> st[N],su[N]; //st[j] is the waiting time for a customer at the jth service point and su[j] is the waiting time for all customers at the jth service point double time[N]; //time[j] is the time spent by the jth customer double greedy(int s) { sort(time.begin(),time.end()); for(int i=0,j=0;i<time.size();i++) //Traverse all customers from small to large { st[j]+=time[i]; su[j]+=st[j]; j++; if(j==s) j=0; //If j exceeds the number of service points, continue from the first service point } double t=0; for(int i=0;i<time.size();i++) t+=su[i]; t/=n; //Calculate the average wait time for all customers at all service points return t; }
18. Shortest path problem
A problem of finding the shortest path from a single source. Given a directed weighted graph G =(V, E), where the weight of each edge is a non-negative real number. In addition, a vertex in a given V is called a source point. Now you will calculate the shortest path length from the source to all other vertices, where the path length refers to the sum of the weights on each side of the road.
basic thought
Set visited vertex set visited, and continue to choose to expand this set until all are true. Initially, visited only has the source vertex set to true, the rest to false, and then update dist[i], which stores the distance from the source vertex to the I vertex, or INT_if not directly connected MAX, then traverse from the first vertex, update the dist, record its lower edges and weights, set the subscript corresponding to the visited array to true to indicate that it has been found, and then update the dist array, keeping in mind that the precondition for updating is:
1. The vertex has not yet been visited (i.e. the shortest path from the source vertex to this vertex has not been found)
2. Make sure that the minimum vertex of this weight found has a directly connected edge to it
3. The sum of the weights is less than the current value of this vertex
The steps are as follows:
- A weighted directed graph is represented by a weighted adjacency matrix matrix, set S to the set of the end points of the currently known shortest path, and its initial state is an empty set. The initial value of the current shortest path length from the source point to vi passing through S to the rest of the graph is dist[i]=matrix[i][j].
- Select Vu so that dist[u]=min{dis[i] | vi belongs to V-S}, that is, vu is the end of the shortest path with Vu marked as visited.
- Modify the current shortest path length from source point v to the rest: if dist[u]+matrix[u][j]<dist[j], modify dist[j]=dist[u]+matrix[u][j].
- Repeat 2, 3 of n-1 times.
//Greedy Algorithm #include<iostream> using namespace std; int matrix[100][100]; //Adjacency Matrix Represents Weighted Directed Graph bool visited[100]; //Tag Array int dist[100]; //Minimum distance from source point to vertex i int path[100]; //Record the shortest path int source; //Source Point int vertex_num; //Number of vertices int arc_num; //Number of Edges void Dijkstra(int source) { visited[source] = true; for (int i = 1; i <= vertex_num; i++) { dist[i] = matrix[source][i]; //dist represents the current shortest special path from the source point to vertex i if(dist[i]!=INT_MAX) path[i] = source; //Records the first vertex of the shortest special path I from the source point to vertex i } int min_cost; //Minimum weight int min_cost_index; //Subscript with minimum weight for (int i = 1; i <= vertex_num; i++) //Find the source point to another vertex_ Shortest path to num-1 point { min_cost = INT_MAX; for (int j = 1; j <= vertex_num; j++) { if (visited[j] == false && dist[j] < min_cost) //Find the Minimum Weight { min_cost = dist[j]; min_cost_index = j; } } visited[min_cost_index] = true; //The point is found and marked for (int j = 1; j <=vertex_num; j++) //Update dist array { if (visited[j] == false && matrix[min_cost_index][j] != INT_MAX && //Ensure that there is an edge between two points matrix[min_cost_index][j] + min_cost < dist[j]) { dist[j] = matrix[min_cost_index][j] + min_cost; path[j] = min_cost_index; } } } } void output() { for (int i = 1; i <= vertex_num; i++) { if (i != source) { cout << source << "reach" << i << "The shortest distance is:" << dist[i] << ",The path is:" << i; for (int t = path[i];t != source; t = path[t]) cout << "--" << t; cout << "--" << source << endl; } } } //Single Source Shortest Path int main() { cin >> vertex_num >> arc_num; for (int i = 0; i <= vertex_num; i++) { for (int j = 0; j <= vertex_num; j++) if(i==j) matrix[i][j]=0; else matrix[i][j] = INT_MAX; //Initialize matrix array } int u, v, w; for (int i = 0; i < arc_num; i++) { cin >> u >> v >> w; matrix[u][v] = w; //Length from u to v is w } cin >> source; Dijkstra(source); output(); return 0; }
19. Hafman coding problems
Algorithmic steps
- Given n n n n n n n weights {W1,W2,W3,..., Wi,..., Wn}, the initial set F= {T1,T2,T3,..., Ti,..., Tn} of N binary trees consists of only one root node with a weight of Wi in each binary tree Ti, and its left and right subtrees are empty.
- In F, two trees with the smallest root node weights are selected as left and right subtrees of the newly constructed binary tree. The root node weights of the new binary tree are the sum of the root nodes of the left and right subtrees.
- Delete the two trees from F and add the new binary tree in descending order (because deleting and adding at the end is more convenient) to the set F.
- Repeat steps two and three until there is only one binary tree in set F.
#include<iostream> #include <vector> #include <algorithm> using namespace std; //Class Definition template<class Type> class Huffman { friend BinaryTree<int> HuffmanTree(Type[],int); public: operator Type() const { return weight; } private: BinaryTree<int> tree; Type weight; }; //Algorithm implementation template<class Type> BinaryTree<int> HuffmanTree(Type f[],int n) //f is the frequency of each character, n is the number of nodes { //Generating a single-node tree Huffuman<Type> *w=new Huffuman<Type>[n+1]; BinaryTree<int> z,zero; //zero is an empty node for(int i=1;i<=n;i++) { z.MakeTree(f[i],zero,zero); w[i].weight=z; w[i].tree=z; //Weight value and tree for position i I } //Create Priority Queue MinHeap<Huffman<Type>> Q(n); for(int i=1;i<=n;i++) Q.Insert(w[i]); //Sort in descending order //Combine Minimum Values Repeatedly Huffuman<Type> x,y; for(int i=1;i<n;i++) //A total of n-1 merges are required { x=Q.RemoveMin(); //Pay x the node with the smallest weight in Q and delete it y=Q.RemoveMin(); z.MakeTree(x.weigt+y.weight,x.tree,y.tree); //Build a binary tree with x and y as son nodes x.weight=z; x.tree=z; Q.Insert(x); } x=Q.RemoveMin(); delete[] w; return x.tree; }
20. Solving the prime number ring problem
#include <iostream> #include<algorithm> #include<cmath> using namespace std; int a[21] = {}, used[21] = {}, flag = 0; int check(int x) { for (int i = 2; i * i <= x; i++) if (x % i == 0) return 0; return 1; } void dfs(int i) { if (flag == 1) return; if (i == 21) { if (flag == 0) { flag = 1; for (int m = 1; m < 20; m++) cout << a[m] << ' '; cout << a[20] << endl; } return; } if (i == 20) { for (int j = 1; j <= 20; j++) if (!used[j] && check(j + a[1])) { a[i] = j; used[j] = 1; dfs(i + 1); used[j] = 0; } } else if (i == 1) { for (int j = 1; j <= 20; j++) { if (!used[j]) { a[i] = j; used[j] = 1; dfs(i + 1); used[j] = 0; } } } else { for (int j = 1; j <= 20; j++) { if (!used[j] && check(j + a[i - 1])) { a[i] = j; used[j] = 1; dfs(i + 1); used[j] = 0; } } } return; } int main() { dfs(1); return 0; }
21. Digital Triangle
#include<iostream> #include<vector> #include<cmath> using namespace std; const int N = 1001; vector <int> a[N]; int main() { int r; cin >> r; for (int i = 1; i <= r; i++) { int x; for (int j = 0; j < i; j++) { cin >> x; a[i].push_back(x); //Adjacency table stores data } } for (int i = r-1; i>=1;i--) //Notice that i starts with r-1 { for (int j = 0; j < i; j++) a[i][j] += max(a[i + 1][j], a[i + 1][j + 1]); } cout << a[1][0]; return 0; }
22. Maximum Integer
#include <iostream> #include <stdlib.h> using namespace std; int n; string a[100]; string result = ""; bool compare(string s1, string s2) { string ts1 = s1 + s2; string ts2 = s2 + s1; if (ts1 > ts2) return false; else return true; } int main() { cin >> n; for (int i = 0; i < n; i++) cin >> a[i]; for (int i = 0; i < n; i++) for (int j = i + 1; j < n; j++) if (compare(a[i], a[j])) { string tmp = a[i]; a[i] = a[j]; a[j] = tmp; } for (int i = 0; i < n; i++) result += a[i]; cout << result << endl; return 0; }
23. Jumping horse problem
#include<iostream> #include<queue> using namespace std; int ans[1001], flag[201][201]; struct brid { int x, y, cnt; }e1,e2; queue <brid> q; int dx[] = { -2,-2,-1,-1,1,1,2,2 }, dy[] = { 1,-1,2,-2,2,-2,1,-1 }; int main() { int n, tx, ty, num = 0; cin >> n; while (n--) { memset(flag, 0, sizeof(flag)); cin >> e1.x >> e1.y >> tx >> ty; flag[e1.x][e1.y] = 1; q.push(e1); while (!q.empty()) { e2 = q.front(); q.pop(); if (e2.x == tx && e2.y == ty) { ans[num++] = e2.cnt; while (!q.empty()) { q.pop(); } break; } for (int i = 0; i < 8; i++) { e1.x = e2.x + dx[i], e1.y = e2.y + dy[i]; if (e1.x < 1 || e1.y < 1 || e1.x>200 || e1.y>200 || flag[e1.x][e1.y]) continue; e1.cnt = e2.cnt + 1; flag[e1.x][e1.y] = 1; q.push(e1); } } e1.cnt = 0, e2.cnt = 0; } for (int i = 0; i < num; i++) cout << ans[i] << endl; return 0; }