#include<bits/stdc++.
h>
using namespace std;
// Merge sort
void merge(vector<int>& arr, int l, int m, int r){
int n1 = m-l+1;
int n2 = r-m;
int left[n1], right[n2];
for(int i=0; i<n1; i++) left[i] = arr[l+i];
for(int i=0; i<n2; i++) right[i] = arr[m+i+1];
int i=0, j=0, k=l;
while(i<n1 && j<n2){
if(left[i] <= right[j]) arr[k++] = left[i++];
else arr[k++] = right[j++];
}
while(i<n1) arr[k++] = left[i++];
while(j<n2) arr[k++] = right[j++];
}
void mergeSort(vector<int>& arr, int l, int r){
if(l>=r) return;
int m = (l+r)/2;
mergeSort(arr,l,m);
mergeSort(arr,m+1,r);
merge(arr,l,m,r);
}
/* int main(){
vector<int> arr = {5,4,6,3,1};
mergeSort(arr,0,5);
for(int i=0; i<5; i++){
cout << arr[i] << " ";
}
return 0;
}*/
// Quick Sort
int partition(vector<int>& arr, int l, int r){
int pivot = arr[l];
int i = l;
for(int j=i+1; j<=r; j++){
if(arr[j] <= pivot){
i++;
swap(arr[i], arr[j]);
}
}
swap(arr[i], arr[l]);
return i;
}
void quickSort(vector<int>& arr, int l, int r){
if(l>=r) return;
int pivot = partition(arr,l,r);
quickSort(arr,l,pivot-1);
quickSort(arr,pivot+1,r);
}
/* int main(){
vector<int> arr = {5,4,6,3,1};
quickSort(arr,0,5);
for(int i=0; i<5; i++){
cout << arr[i] << " ";
}
return 0;
} */
// 0/1 knapsack using dp
/* int main(){
int n = 4;
vector<int> wt = {30,10,40,20};
vector<int> p = {10,20,30,40};
int W = 40;
int dp[n+1][W+1];
for(int i=0; i<=n; i++){
for(int w=0; w<=W; w++){
if(i==0 || w==0) dp[i][w] = 0;
else if(wt[i-1] <= w){
dp[i][w] = max(p[i-1] + dp[i-1][w-wt[i-1]], dp[i-1][w]);
}
else dp[i][w] = dp[i-1][w];
}
}
cout << "Maximum Profit = " << dp[n][W] << endl;
int w = W;
vector<int> selectedItems;
for(int i=n; i>0 && w>0; i--){
if(dp[i-1][w]!=dp[i][w]){
selectedItems.push_back(i);
w = w - wt[i-1];
}
}
cout << "Selected items : ";
for(int i = 0; i < [Link](); i++){
cout << selectedItems[i] << " ";
}
return 0;
} */
// matrix chain multiplication using dp
void printParenthesis(int i, int j, vector<vector<int>> k_mat, char& ch){
if(i==j){
cout << ch++;
return;
}
cout << "(";
printParenthesis(i, k_mat[i][j], k_mat, ch);
printParenthesis(k_mat[i][j]+1, j, k_mat, ch);
cout << ")";
}
/*int main(){
int n = 5;
vector<int> d = {1,2,3,4,3};
vector<vector<int>> dp(n,vector<int>(n,0));
vector<vector<int>> k_mat(n,vector<int>(n,0));
for(int L=2; L<n; L++){
for(int i=1; i<n-L+1; i++){
int j = i+L-1;
dp[i][j] = INT_MAX;
for(int k=i; k<j; k++){
int q = dp[i][k] + dp[k+1][j] + d[i-1]*d[j]*d[k];
if(q < dp[i][j]){
dp[i][j] = q;
k_mat[i][j] = k;
}
}
}
}
cout << "Min no. of multiplications : " << dp[1][n-1] << endl;
cout << "Matrix Chain Matrix : " << endl;
for(int i=1; i<n; i++){
for(int j=1; j<n; j++){
if(dp[i][j] == 0 && i!=j) cout << " \t";
else cout << dp[i][j] << "\t";
}
cout << endl;
}
cout << endl;
cout << "K Matrix : " << endl;
for(int i=1; i<n; i++){
for(int j=1; j<n; j++){
if(k_mat[i][j] == 0 && i!=j) cout << " \t";
else cout << k_mat[i][j] << "\t";
}
cout << endl;
}
cout << endl;
cout << "Parenthesization : ";
char ch = 'A';
printParenthesis(1, n-1, k_mat, ch);
return 0;
}*/
// fractional knapsack greedy;
struct Item{
int weight;
int profit;
double ratio;
Item(int w, int p){
weight = w;
profit = p;
ratio = (double)p/w;
}
};
bool cmp(Item a, Item b){
return [Link] > [Link];
}
double fractionalKnapsack(vector<Item> items, int capacity){
sort([Link](), [Link](), cmp);
int maxProfit = 0;
int remCap = capacity;
for(int i=0; i<[Link](); i++){
double ratio = items[i].ratio;
int weight = items[i].weight;
int profit = items[i].profit;
if(remCap >= weight){
maxProfit += profit;
remCap -= weight;
}
else{
maxProfit += ratio*remCap;
remCap = 0;
}
}
return maxProfit;
}
/* int main(){
int capacity = 50;
vector<Item> items = {
Item(10, 60),
Item(20, 100),
Item(30, 120)
};
double ans = fractionalKnapsack(items, capacity);
cout << "Max Profiit = " << ans;
return 0;
} */
// huffman coding greedy
struct Node{
char data;
int freq;
Node* left;
Node* right;
Node(char d, int f){
data = d;
freq = f;
left = nullptr;
right = nullptr;
}
};
struct comp{
bool operator()(Node* a, Node* b){
return (a->freq) > (b->freq);
}
};
Node* buildHuffmanTree(vector<char> chars, vector<int> freq){
priority_queue<Node*, vector<Node*>, comp> pq;
for(int i=0; i<[Link](); i++){
[Link](new Node(chars[i], freq[i]));
}
while([Link]() > 1){
Node* x = [Link]();
[Link]();
Node* y = [Link]();
[Link]();
Node* z = new Node('#', x->freq + y->freq);
z->left = x;
z->right = y;
[Link](z);
}
return [Link]();
}
void huffmanCodes(Node* root, unordered_map<char, string>& codes, string code){
if(root == nullptr) return;
if(root->left == nullptr && root->right == nullptr){
codes[root->data] = code;
return;
}
huffmanCodes(root->left, codes, code + '0');
huffmanCodes(root->right, codes, code + '1');
}
void printHuffmanCodes(Node* root){
unordered_map<char, string> codes;
huffmanCodes(root, codes, "");
for(unordered_map<char, string>::iterator it = [Link](); it != [Link]();
it++){
cout << it->first << " : " << it->second << endl;
}
}
/* int main(){
vector<char> characters = {'a', 'b', 'c', 'd', 'e', 'f'};
vector<int> frequencies = {5, 9, 12, 13, 16, 45};
Node* root = buildHuffmanTree(characters, frequencies);
cout << "Huffman Codes : " << endl;
printHuffmanCodes(root);
return 0;
}*/
// prims
void prims(int E, int V, vector<vector<pair<int,int>>> graph){
int totalCost = 0;
vector<int> cost(V, INT_MAX);
vector<int> parent(V, -1);
vector<bool> inMST(V, false);
priority_queue<pair<int,int>, vector<pair<int,int>>, greater<pair<int,int>>> pq;
cost[0] = 0;
[Link]({0,0});
while(![Link]()){
int u = [Link]().second;
[Link]();
if(inMST[u]) continue;
totalCost += cost[u];
inMST[u] = true;
for(int i=0; i<graph[u].size(); i++){
int v = graph[u][i].first;
int c = graph[u][i].second;
if(!inMST[v] && c < cost[v]){
cost[v] = c;
parent[v] = u;
[Link]({c,v});
}
}
}
cout << "Edges in MST : " << endl;
for(int i=1; i<V; i++){
cout << "Edge : " << parent[i] << "->" << i << " | Cost : " << cost[i] <<
endl;
}
cout << "Total Cost of MST = " << totalCost;
}
/* int main(){
int V;
cout << "Enter No. of Vertex : ";
cin >> V;
int E;
cout << "Enter No. of Edges : ";
cin >> E;
vector<vector<pair<int,int>>> graph(V);
cout << "Enter Edges (Src, Dest, Cost) : ";
for(int i=0; i<E; i++){
int u,v,c;
cin >> u >> v >> c;
graph[u].push_back({v,c});
graph[v].push_back({u,c});
}
prims(E,V,graph);
return 0;
} */
// kruskal
class DisjointSet{
vector<int> rank;
vector<int> parent;
public:
DisjointSet(int n){
[Link](n+1, 0);
[Link](n+1);
for(int i=0; i<=n; i++) parent[i] = i;
}
int Find(int u){
if(u == parent[u]) return u;
return parent[u] = Find(parent[u]);
}
void Union(int u, int v){
int pu = Find(u);
int pv = Find(v);
if(pu == pv) return;
if(rank[pu] < rank[pv]){
parent[pu] = pv;
}
else if(rank[pv] < rank[pu]){
parent[pv] = pu;
}
else{
parent[pv] = pu;
rank[pu]++;
}
}
};
bool comparator(vector<int> a, vector<int> b){
return a[2] < b[2];
}
void kruskal(int E, int V, vector<vector<int>> edges){
sort([Link](), [Link](), comparator);
DisjointSet ds(V);
int totalCost = 0;
vector<pair<pair<int,int>, int>> mst;
for(int i=0; i<E; i++){
int u = edges[i][0];
int v = edges[i][1];
int ct = edges[i][2];
if([Link](u) != [Link](v)){
totalCost += ct;
mst.push_back({{u,v},ct});
[Link](u,v);
}
}
cout << "Edges in MST : " << endl;
for(int i=0; i<[Link](); i++){
cout << mst[i].[Link] << "->" << mst[i].[Link] << " | Cost : " <<
mst[i].second << endl;
}
cout << "Total Cost = " << totalCost;
}
/* int main(){
int V;
cout << "Enter No. of Vertex : ";
cin >> V;
int E;
cout << "Enter No. of Edges : ";
cin >> E;
vector<vector<int>> edges(E, vector<int>(3));
cout << "Enter Edges (Src, Dest, Cost) : " << endl;
for(int i=0; i<E; i++){
for(int j=0; j<3; j++){
cin >> edges[i][j];
}
}
kruskal(E,V,edges);
return 0;
} */
// dijkstra
vector<int> dijkstra(int V, int E, vector<vector<pair<int,int>>> graph, int src){
vector<int> dist(V, INT_MAX);
priority_queue<pair<int,int>, vector<pair<int,int>>, greater<pair<int,int>>> pq;
dist[src] = 0;
[Link]({0,src});
while(![Link]()){
int u = [Link]().second;
int d = [Link]().first;
[Link]();
for(int i=0; i<graph[u].size(); i++){
int v = graph[u][i].first;
int wt = graph[u][i].second;
if(d + wt < dist[v]){
dist[v] = d + wt;
[Link]({dist[v], v});
}
}
}
return dist;
}
/* int main(){
int V;
cout << "Enter No. of Vertex : ";
cin >> V;
int E;
cout << "Enter No. of Edges : ";
cin >> E;
vector<vector<pair<int,int>>> graph(V);
cout << "Enter Edges (Src, Dest, Weight) : " << endl;
for(int i=0; i<E; i++){
int u,v,w;
cin >> u >> v >> w;
graph[u].push_back({v,w});
graph[v].push_back({u,w});
}
int s;
cout << "Enter Source node : ";
cin >> s;
vector<int> dist = dijkstra(V,E,graph,s);
cout << "Shortest Distance from : " << endl;
for(int i=0; i<[Link](); i++){
cout << s << " to " << i << " = " << dist[i] << endl;
}
return 0;
} */
// bellman ford
vector<int> bellmanFord(int V, int E, vector<vector<int>> edges, int src){
vector<int> dist(V, INT_MAX);
dist[src] = 0;
for(int i=0; i<V-1; i++){
for(int j=0; j<[Link](); j++){
int u = edges[j][0];
int v = edges[j][1];
int d = edges[j][2];
if(dist[u]!=INT_MAX && d + dist[u] < dist[v]){
dist[v] = d + dist[u];
}
}
}
for(int j=0; j<[Link](); j++){
int u = edges[j][0];
int v = edges[j][1];
int d = edges[j][2];
if(dist[u]!=INT_MAX && d + dist[u] < dist[v]){
cout << "Negative cycle detected !";
return {-1};
}
}
return dist;
}
/* int main(){
int V;
cout << "Enter No. of Vertex : ";
cin >> V;
int E;
cout << "Enter No. of Edges : ";
cin >> E;
vector<vector<int>> edges(E, vector<int>(3));
cout << "Enter Edges (Src, Dest, Weight) : " << endl;
for(int i=0; i<E; i++){
for(int j=0; j<3; j++){
cin >> edges[i][j];
}
}
int s;
cout << "Enter Source node : ";
cin >> s;
vector<int> dist = bellmanFord(V,E,edges,s);
cout << "Shortest Distance from : " << endl;
for(int i=0; i<[Link](); i++){
cout << s << " to " << i << " = " << dist[i] << endl;
}
return 0;
} */
// rabin karp
void rabinKarp(string t, string p, int q){
int n = [Link]();
int m = [Link]();
int hash_t = 0;
int hash_p = 0;
int d = 256;
int h = 1;
int i,j;
for(i=0; i<m-1; i++){
h = (h*d)%q;
}
for(i=0; i<m; i++){
hash_t = (d*hash_t + t[i])%q;
hash_p = (d*hash_p + p[i])%q;
}
for(i=0; i<=n-m; i++){
if(hash_t == hash_p){
for(j=0; j<m; j++){
if(t[i+j]!=p[j]) break;
}
if(j==m) cout << "Pattern found at index " << i << endl;
}
if(i < n-m){
hash_t = (d*(hash_t - t[i]*h) + t[i+m]) % q;
if(hash_t < 0) hash_t += q;
}
}
}
/* int main(){
string t = "atharvar";
string p = "ar";
rabinKarp(t,p,101);
} */
// KMP
vector<int> findLPS(string p){
int m = [Link]();
vector<int> lps(m,0);
int j = 0;
for(int i=1; i<m; i++){
while(j>0 && p[i]!=p[j]){
j = lps[j-1];
}
if(p[i] == p[j]) j++;
lps[i] = j;
}
return lps;
}
void kmpMatcher(string t, string p){
int n = [Link]();
int m = [Link]();
vector<int> lps = findLPS(p);
int j=0;
for(int i=0; i<n; i++){
while(j>0 && t[i]!=p[j]){
j = lps[j-1];
}
if(t[i] == p[j]) j++;
if(j==m){
cout << "Pattern found at index " << i-m+1 << endl;
j = lps[j-1];
}
}
}
/* int main(){
string t = "atharvar";
string p = "ar";
kmpMatcher(t,p);
return 0;
} */
// Ford fulkerson
bool bfs(int V, vector<vector<int>>& graph, int s, int t, vector<int>& parent){
vector<bool> vis(V, false);
queue<int> q;
vis[s] = true;
parent[s] = -1;
[Link](s);
while(![Link]()){
int u = [Link]();
[Link]();
for(int v=0; v<V; v++){
if(!vis[v] && graph[u][v]){
vis[v] = true;
parent[v] = u;
[Link](v);
if(v==t) return true;
}
}
}
return false;
}
int fordFulkerson(int V, vector<vector<int>> graph, int s, int t){
vector<int> parent(V, -1);
int maxFlow = 0;
cout << "Augmenting Paths : " << endl;
while(bfs(V,graph,s,t,parent)){
int pathFlow = INT_MAX;
for(int v=t; v!=s; v=parent[v]){
int u = parent[v];
pathFlow = min(pathFlow, graph[u][v]);
}
cout << "Path : ";
for(int v=t; v!=s; v=parent[v]){
cout << v << "<- ";
}
cout << s << ", Bottleneck = " << pathFlow << endl;
for(int v=t; v!=s; v=parent[v]){
int u = parent[v];
graph[u][v] -= pathFlow;
graph[v][u] += pathFlow;
}
maxFlow += pathFlow;
}
return maxFlow;
}
/* int main(){
int V;
cout << "Enter No. of Vertex : ";
cin >> V;
int E;
cout << "Enter No. of Edges : ";
cin >> E;
vector<vector<int>> graph(V, vector<int>(V));
cout << "Enter Edges (Src, Dest, Capacity) : " << endl;
for(int i=0; i<E; i++){
int u,v,c;
cin >> u >> v >> c;
graph[u][v] = c;
}
int s,t;
cout << "Enter Source and Sink : ";
cin >> s >> t;
cout << "Maximum Flow = " << fordFulkerson(V,graph,s,t);
} */
// max bipartite matching
bool bmp(int u,int U, int V, vector<vector<int>>& graph, vector<bool>& vis,
vector<int>& match){
for(int v=0; v<V; v++){
if(!vis[u] && graph[u][v]){
vis[v] = true;
if(match[v] < 0 || bmp(v,U,V,graph,vis,match)){
match[v] = u;
return true;
}
}
}
return false;
}
int maxMatching(int U, int V, vector<vector<int>> graph){
vector<int> match(V, -1);
int maxMatch = 0;
for(int u=0; u<U; u++){
vector<bool> vis(V, false);
if(bmp(u,U,V,graph,vis,match)){
maxMatch++;
}
}
return maxMatch;
}
/* int main(){
int U;
cout << "Enter No. of vertex on left side : ";
cin >> U;
int V;
cout << "Enter No. of vertex on right side : ";
cin >> V;
int E;
cout << "Enter No. of edges : ";
cin >> E;
vector<vector<int>> graph(U, vector<int>(V,0));
cout << "Enter Edges (Src, Dest) : ";
for(int i=0; i<E; i++){
int u,v;
cin >> u >> v;
graph[u][v] = 1;
}
cout << "Max MAtch = " << maxMatching(U,V,graph);
} */
// subset sum
void subsetSum(vector<int> nums, int target, int idx, vector<int>& curr,
vector<vector<int>>& result){
if(target == 0){
result.push_back(curr);
return;
}
if([Link]() == idx) return;
if(nums[idx] <= target){
curr.push_back(nums[idx]);
subsetSum(nums, target-nums[idx], idx+1, curr, result);
curr.pop_back();
}
subsetSum(nums, target, idx+1, curr, result);
}
vector<vector<int>> findsubsetSum(vector<int> nums, int target){
vector<vector<int>> result;
vector<int> curr;
subsetSum(nums,target,0,curr,result);
return result;
}
/* int main(){
vector<int> nums = {10,20,30,40};
int target = 50;
vector<vector<int>> subsets = findsubsetSum(nums, target);
cout << "The Subsets are:\n";
for (int i = 0; i < [Link](); ++i) {
cout << "{";
for (int j = 0; j < subsets[i].size(); ++j) {
cout << subsets[i][j] << " ";
}
cout << "}" << endl;
}
} */
// n queen
int N;
vector<vector<int>> board;
bool issafe(int row, int col){
for(int i=0; i<row; i++) if(board[i][col]) return false;
for(int i=row-1, j=col-1; i>=0 && j>=0; i--,j--) if(board[i][j]) return false;
for(int i=row-1, j=col+1; i>=0 && j<N; i--,j++) if(board[i][j]) return false;
return true;
}
bool solve(int row){
if(row == N) return true;
for(int col=0; col<N; col++){
if(issafe(row, col)){
board[row][col] = 1;
if(solve(row+1)) return true;
board[row][col] = 0;
}
}
return false;
}
void printBoard(){
for(int i = 0; i < N; i++){
for(int j = 0; j < N; j++){
cout << (board[i][j] ? "Q " : ". ");
}
cout << endl;
}
}
/* int main(){
N = 4;
board = vector<vector<int>>(N, vector<int>(N,0));
if(solve(0)) printBoard();
else cout << "No solution exists for " << N << " queens.\n";
return 0;
} */
// set cover
struct Subset{
set<int> elements;
int cost;
};
void setCover(set<int> U, vector<Subset> subsets){
vector<int> setCovered;
map<int, double> price;
double totalCost = 0;
while(![Link]()){
double minAlpha = DBL_MAX;
int idx = -1;
set<int> bestNewElements;
for(int i=0; i<[Link](); i++){
set<int> newElements;
for(int e : subsets[i].elements){
if([Link](e) != [Link]()){
[Link](e);
}
}
if(![Link]()){
double alpha = subsets[i].cost / [Link]();
if(alpha < minAlpha){
alpha = minAlpha;
idx = i;
bestNewElements = newElements;
}
}
}
if(idx==-1) break;
for(int e : bestNewElements){
price[e] = minAlpha;
[Link](e);
}
setCovered.push_back(idx);
totalCost += subsets[idx].cost;
}
cout << "Set Covered : ";
for(int i=0; i<[Link](); i++){
cout << "S" << setCovered[i]+1 << " ";
}
cout << endl;
cout << "Total Cost = " << totalCost;
}
/* int main(){
set<int> U = {1,2,3,4,5};
vector<Subset> subsets = {
{{4,1,3}, 5},
{{2,5}, 10},
{{1,2,3,4},3 },
};
setCover(U, subsets);
} */
// vertex cover
vector<int> vertexCover(int V, int E, vector<vector<int>> graph){
vector<int> cover;
vector<bool> included(V, false);
for(int u=0; u<V; u++){
if(!included[u]){
for(int i=0; i<graph[u].size(); i++){
int v = graph[u][i];
if(!included[v]){
included[u] = true;
included[v] = true;
cover.push_back(u);
cover.push_back(v);
break;
}
}
}
}
return cover;
}
/* int main(){
int V;
cout << "Enter No. of Vertex : ";
cin >> V;
int E;
cout << "Enter No. of Edges : ";
cin >> E;
vector<vector<int>> graph(V);
cout << "Enter Edges (Src, Dest, Cost) : ";
for(int i=0; i<E; i++){
int u,v;
cin >> u >> v;
graph[u].push_back(v);
graph[v].push_back(u);
}
vector<int> cover = vertexCover(V,E,graph);
for(int i=0; i<[Link](); i++){
cout << cover[i] << " ";
}
return 0;
} */
// 0/1 knapsack using branch and bound
struct item{
int profit;
int weight;
double ratio;
item(int w, int p){
profit = p;
weight = w;
ratio = (double)p/w;
}
};
struct node{
int profit, weight,level;
double bound;
};
bool comapre(item a, item b){
return [Link] > [Link];
};
double findBound(node u, int W, int n, vector<item>& items){
if([Link] >= W) return 0;
double profitBound = [Link];
int weight = [Link];
int j = [Link]+1;
while(j<n && weight + items[j].weight <= W){
profitBound += items[j].profit;
weight += items[j].weight;
j++;
}
if(j < n) profitBound += (W - weight)*items[j].ratio;
return profitBound;
}
int knapsack(int W, int n, vector<item> items){
int maxProfit = 0;
sort([Link](), [Link](), comapre);
node u,v;
[Link] = 0;
[Link] = 0;
[Link] = -1;
[Link] = findBound(u,W,n,items);
queue<node> q;
[Link](u);
while(![Link]()){
u = [Link]();
[Link]();
if([Link] == n-1) continue;
[Link] = [Link] + 1;
[Link] = [Link] + items[[Link]].profit;
[Link] = [Link] + items[[Link]].weight;
if([Link] <= W && [Link] > maxProfit){
maxProfit = [Link];
}
[Link] = findBound(v,W,n,items);
if([Link] > maxProfit){
[Link](v);
}
[Link] = [Link];
[Link] = [Link];
[Link] = findBound(v,W,n,items);
if([Link] > maxProfit){
[Link](v);
}
}
return maxProfit;
}
/* int main() {
int W = 15;
vector<item> items = {
item(2, 10),
item(4, 10),
item(6, 12),
item(9, 18),
};
int n = [Link]();
cout << "Maximum profit is " << knapsack(W, n, items) << endl;
return 0;
} */
// 15 puzzle using branch and bound
int n = 4;
vector<vector<int>> goal = {
{1,2,3,4},
{5,6,7,8},
{9,10,11,12},
{13,14,15,0}
};
struct Nodes{
vector<vector<int>> board;
int x, y;
int level;
int cost;
Nodes* parent;
Nodes(vector<vector<int>> b, int x, int y, int new_x, int new_y, int l, Nodes* p){
board = b;
swap(board[x][y], board[new_x][new_y]);
this->x = new_x;
this->y = new_y;
level = l;
cost = INT_MAX;
parent = p;
}
};
int calculateCost(vector<vector<int>> board){
int dist = 0;
for(int i=0; i<n; i++){
for(int j=0; j<n; j++){
int val = board[i][j];
if(val!=0){
int target_x = (val-1)/n;
int target_y = (val-1)%n;
dist += abs(i-target_x) + abs(j-target_y);
}
}
}
return dist;
}
void printBoard(vector<vector<int>> board){
for(int i=0; i<n; i++){
for(int j=0; j<n; j++){
cout << board[i][j] << " ";
}
cout << endl;
}
}
void printPath(Nodes* root){
if(root == nullptr) return;
printPath(root->parent);
printBoard(root->board);
}
bool isGoal(vector<vector<int>> board){
return goal == board;
}
struct c{
bool operator()(Nodes* a, Nodes* b){
return (a->cost) > (b->cost);
}
};
string boardToString(vector<vector<int>> board){
string s;
for(int i=0; i<n; i++){
for(int j=0; j<n; j++){
s += to_string(board[i][j]) + ",";
}
}
return s;
}
void solvePuzzle(vector<vector<int>> board){
int x,y;
for(int i=0; i<n; i++){
for(int j=0; j<n; j++){
if(board[i][j] == 0){
x = i;
y = j;
}
}
}
priority_queue<Nodes*, vector<Nodes*>, c> pq;
set<string> visited;
Nodes* root = new Nodes(board, x,y,x,y,0,nullptr);
[Link](root);
while(![Link]()){
Nodes* minNode = [Link]();
[Link]();
string key = boardToString(minNode->board);
if([Link](key)) continue;
[Link](key);
if(isGoal(minNode->board)){
cout << "Solved in " << minNode->level << "moves";
printPath(minNode);
return;
}
int dx[] = {1,-1,0,0};
int dy[] = {0,0,1,-1};
for(int i=0; i<4; i++){
int new_x = minNode->x + dx[i];
int new_y = minNode->y + dy[i];
if(new_x>=0 && new_x<n && new_y>=0 && new_y<n){
Nodes* child = new Nodes(minNode->board, minNode->x, minNode->y,
new_x, new_y, minNode->level+1, minNode);
child->cost = calculateCost(child->board) + child->level;
[Link](child);
}
}
}
}
/* int main() {
vector<vector<int>> initial = {
{1, 2, 3, 4},
{5, 6, 0, 8},
{9,10, 7,11},
{13,14,15,12}
};
solvePuzzle(initial);
return 0;
} */