Google Kickstart Round A 2021-Rabbit House - algorithm

could anyone tell me what's wrong with my code? I've passed the sample tests, but I couldn't pass both of the actual test cases..
My algorithm is to dfs:
Going from the first element of a matrix till the end, check if the difference between an element and the adjacent upper, lower, left, right is less than or equal to 1
If so then pass
If not then add the minimum number of blocks to either the checking element or the adjacent one to make the difference 1
And increase the count by the minimum number of blocks you added
How to add the minimum number to which element:
Just choose the smaller element the minimum required to make the absolute difference 1
Say for example, you compared aij with the lower one ai+1j:
If you added to the checking element because it was smaller, then recurse again starting at aij+1, aij-1, ai-1j. Because now the difference between aij and ai+1j meets the criteria you need to check if it is so with other adjacent ones
Otherwise recurse starting at ai+1j
Do the stepe above for lower, upper, left, right
6.return count
Here is the problem:
https://codingcompetitions.withgoogle.com/kickstart/round/0000000000436140/000000000068cb14
Problem
Barbara got really good grades in school last year, so her parents decided to gift her with a pet rabbit. She was so excited that she built a house for the rabbit, which can be seen as a 2D grid with R rows and C columns.
Rabbits love to jump, so Barbara stacked several boxes on several cells of the grid. Each box is a cube with equal dimensions, which match exactly the dimensions of a cell of the grid.
However, Barbara soon realizes that it may be dangerous for the rabbit to make jumps of height greater than 1 box, so she decides to avoid that by making some adjustments to the house. For every pair of adjacent cells, Barbara would like that their absolute difference in height be at most 1 box. Two cells are considered adjacent if they share a common side.
As all the boxes are superglued, Barbara cannot remove any boxes that are there initially, however she can add boxes on top of them. She can add as many boxes as she wants, to as many cells as she wants (which may be zero). Help hew determine what is the minimum total number of boxes to be added so that the rabbit's house is safe.
Input
The first line of the input gives the number of test cases, T. T test cases follow.
Each test case begins with a line containing two integers R and C.
Then, R lines follow, each with C integers. The j-th integer on i-th line, Gi,j, represents how many boxes are there initially on the cell located at the i-th row and j-th column of the grid.
Output
For each test case, output one line containing Case #x: y, where x is the test case number (starting from 1) and y is the minimum number of boxes to be added so that the rabbit's house is safe.
Limits
Memory limit: 1 GB.
1≤T≤100.
0≤Gi,j≤2⋅106, for all i, j.
Test Set 1
Time limit: 20 seconds.
1≤R,C≤50.
Test Set 2
Time limit: 40 seconds.
1≤R,C≤300.
This is my code in C++:
#include <iostream>
#include <string>
#include <cstdlib>
#include <vector>
using namespace std;
void solve(vector<vector<int>> &v,
int ii, int jj,
int r, int c, int& cnt) {
if (ii<0 || ii>r - 1 || jj<0 || jj>c - 1) return;
int ads;
if (ii + 1 < r) {
if (abs(v[ii][jj] - v[ii + 1][jj]) > 1) {
ads = min(abs(v[ii + 1][jj] - v[ii][jj] - 1),
abs(v[ii + 1][jj] - v[ii][jj] + 1));
cnt += ads;
if (v[ii + 1][jj] < v[ii][jj]) {
v[ii + 1][jj] += ads;
solve(v, ii + 1, jj, r, c, cnt);
}
else {
v[ii][jj] += ads;
solve(v, ii, jj - 1, r, c, cnt);
solve(v, ii, jj + 1, r, c, cnt);
solve(v, ii - 1, jj, r, c, cnt);
}
}
}
if (ii - 1 > -1) {
if (abs(v[ii][jj] - v[ii - 1][jj]) > 1) {
ads = min(abs(v[ii - 1][jj] - v[ii][jj] - 1),
abs(v[ii - 1][jj] - v[ii][jj] + 1));
cnt += ads;
if (v[ii - 1][jj] < v[ii][jj]) {
v[ii - 1][jj] += ads;
solve(v, ii - 1, jj, r, c, cnt);
}
else {
v[ii][jj] += ads;
solve(v, ii, jj - 1, r, c, cnt);
solve(v, ii, jj + 1, r, c, cnt);
solve(v, ii + 1, jj, r, c, cnt);
}
}
}
if (jj - 1 > -1) {
if (abs(v[ii][jj] - v[ii][jj - 1]) > 1) {
ads = min(abs(v[ii][jj - 1] - v[ii][jj] - 1),
abs(v[ii][jj - 1] - v[ii][jj] + 1));
cnt += ads;
if (v[ii][jj - 1] < v[ii][jj]) {
v[ii][jj - 1] += ads;
solve(v, ii, jj - 1, r, c, cnt);
}
else {
v[ii][jj] += ads;
solve(v, ii, jj + 1, r, c, cnt);
solve(v, ii - 1, jj, r, c, cnt);
solve(v, ii + 1, jj, r, c, cnt);
}
}
}
if (jj + 1 < c) {
if (abs(v[ii][jj] - v[ii][jj + 1]) > 1) {
ads = min(abs(v[ii][jj + 1] - v[ii][jj] - 1),
abs(v[ii][jj + 1] - v[ii][jj] + 1));
cnt += ads;
if (v[ii][jj + 1] < v[ii][jj]) {
v[ii][jj + 1] += ads;
solve(v, ii, jj + 1, r, c, cnt);
}
else {
v[ii][jj] += ads;
solve(v, ii, jj - 1, r, c, cnt);
solve(v, ii - 1, jj, r, c, cnt);
solve(v, ii + 1, jj, r, c, cnt);
}
}
}
return;
}
int main() {
// your code goes here
int t;
cin>>t;
int r, c, m;
for (int i = 0; i < t; i++) {
cin >> r >> c;
vector<vector<int>> v(r,vector<int>(c,0));
for (int j=0;j<r;j++){
for (int k=0;k<c;k++){
cin>>m;
v[j][k]=m;
}
}
int cnt=0;
for (int j=0;j<r;j++){
for (int k=0;k<c;k++){
solve(v,j,k,r,c,cnt);
}
}
cout << "Case #" << i + 1 << ": " << cnt<<endl;
}
return 0;
}
I've passed the sample cases:
Sample
Sample Input
3
1 3
3 4 3
1 3
3 0 0
3 3
0 0 0
0 2 0
0 0 0
Sample Output
Case #1: 0
Case #2: 3
Case #3: 4
but not the actual test cases...any help much appreciated!!

As already indicated in comments, the solution is to start from the highest box, and to set the height value of its neighbours if needed.
A naive implementation is O(n^2).
As suggested in comments, I tried to use a max-heap. However, this solution was not fast enough (TLE) because once the height values of the matrix are updated, the max-heap has to be rebuilt. I might be posible to improve this implementation. I prefered to follow another way.
Finally, I got a fast enough solution by using a std::multiset, with a dedicated comparator.
When the height of a cell is updated, it is removed and reinserted in the multiset, each operation being O(logn).
Global complexity: O(n logn), where n is the number of elements `n = R * C* of the matrix.
#include <iostream>
#include <string>
#include <cstdlib>
#include <vector>
#include <algorithm>
#include <set>
#include <iterator>
struct Coord {
int x;
int y;
friend std::ostream& operator<<(std::ostream& os, const Coord& c) {
os << "(" << c.x << ", " << c.y << ")";
return os;
}
};
long long int solution (std::vector<std::vector<int>>& heights, int R, int C) {
std::vector<Coord> depl = {{-1, 0}, {1, 0}, {0, -1}, {0, 1}};
long long int count = 0;
auto Comp = [&heights] (const Coord& c0, const Coord& c1) {
if (heights[c0.x][c0.y] == heights[c1.x][c1.y]) {
if (c0.x == c1.x) return (c0.y < c1.y);
return (c0.x < c1.x);
}
return heights[c0.x][c0.y] > heights[c1.x][c1.y];
};
std::multiset<Coord, decltype(Comp)> Cells (Comp);
for (int i = 0; i < R; ++i) {
for (int j = 0; j < C; ++j) {
Cells.insert ({i, j});
}
}
auto isValid = [&] (int i, int j) {
return (i >= 0) && (i < R) && (j >= 0) && (j < C);
};
while (Cells.size() > 1) {
auto n = Cells.size();
auto top = Cells.begin();
auto pivot = *top;
int h_ref = heights[pivot.x][pivot.y];
Cells.erase (top);
for (auto& d: depl) {
int x = pivot.x + d.x;
int y = pivot.y + d.y;
if (!isValid(x, y)) continue;
int h = heights[x][y];
if (h <= h_ref - 2) {
count += h_ref - h - 1;
Cells.erase({x, y});
heights[x][y] = h_ref - 1;
Cells.insert({x, y});
}
}
}
return count;
}
int main() {
std::ios_base::sync_with_stdio(false);
std::cin.tie(NULL);
std::cout.tie(0);
int nt;
std::cin >> nt;
for (int t = 1; t <= nt; t++) {
int R, C;
std::cin >> R >> C;
std::vector<std::vector<int>> v(R, std::vector<int>(C));
for (int j = 0; j < R; j++) {
for (int k = 0; k < C; k++) {
int m;
std::cin >> m;
v[j][k] = m;
}
}
auto cnt = solution (v, R, C);
std::cout << "Case #" << t << ": " << cnt << std::endl;
}
return 0;
}

Related

Josephus Permutation (Removal Order) in O(n.logn)

Is there a way to print out the order of removal in the Josephus problem in O(n.logn) ?
Example
With number of people is n = 7 and number of skip k = 3. The order of elimination would be:
3, 6, 2, 7, 5, 1, 4
There's an approach that uses ordered set
(https://www.geeksforgeeks.org/ordered-set-gnu-c-pbds/):
Initialize an ordered set V, and insert the elements in the range [1, N] into V.
Initialize a variable, say pos as 0, to store the index of the removed element.
Iterate until the size of V is greater than 1, and perform the following steps:
Store the size of the set in a variable, say X
Update the value of pos to (pos + K) % X
Print the element pointed by pos in V and then erase it
Update pos to pos%V.size()
Print the last element stored at the beginning of set V
Here's the code:
#include <iostream>
using namespace std;
// Header files, namespaces to use
// ordered set
#include <ext/pb_ds/assoc_container.hpp>
#include <ext/pb_ds/tree_policy.hpp>
using namespace __gnu_pbds;
#define ordered_set \
tree<int, null_type, less<int>, rb_tree_tag, \
tree_order_statistics_node_update>
// Function to find the person who
// will get killed in the i'th step
void orderOfExecution(int N, int K)
{
// Create an ordered set
ordered_set V;
// Push elements in the range
// [1, N] in the set
for (int i = 1; i <= N; ++i)
V.insert(i);
// Stores the position to be removed
int pos = 0;
// Iterate until the size of the set
// is greater than 1
while (V.size() > 1) {
// Update the position
pos = (pos + K) % (int)V.size();
// Print the removed element
cout << *(V.find_by_order(pos)) << ' ';
// Erase it from the ordered set
V.erase(*(V.find_by_order(pos)));
// Update position
pos %= (int)V.size();
}
// Print the first element of the set
cout << *(V.find_by_order(0));
}
int main()
{
int N = 5, K = 2;
// Function Call
orderOfExecution(N, K);
return 0;
}
Time Complexity: O(N * log(N))
For better understanding, I recommend checking out this video:
https://youtu.be/KnsDFCcBJbY
You can build segment tree that can solve these type of operations
M(p, v): Modify a[p] := v
S(l, r): Calculate a[l] + a[l+1] + ... + a[r]
F(p, k): Find min(x) that (x >= p) and S(1, x) >= k
All of above operations can be done in O(log n) time
Using the algorithm described above you can achieve same result in O(n log n)
/*
#Author: SPyofgame
#License: Free to use
*/
#include <iostream>
#include <vector>
using namespace std;
/// Segment Tree Data Structure
struct Segtree
{
int n;
vector<int> t;
/// O(n)
/// Construct Segment Tree
void init(int lim)
{
for (n = 1; n < lim; n <<= 1);
t.assign(n << 1, 0);
}
/// O(log n)
/// Modify: a[pos] := v
void modify(int pos, int v, int ct, int lt, int rt)
{
if (rt - lt == 1)
{
t[ct] = v;
return ;
}
int mt = (lt + rt) >> 1;
if (mt > pos)
modify(pos, v, ct * 2 + 1, lt, mt);
else
modify(pos, v, ct * 2 + 2, mt, rt);
t[ct] = t[ct * 2 + 1] + t[ct * 2 + 2];
}
/// O(log n)
void modify(int pos, int v)
{
return modify(pos, v, 0, 0, n);
}
/// O(log n)
/// Query: Sigma(a[i] | l <= i <= r)
int query(int l, int r, int ct, int lt, int rt)
{
if (lt >= r || l >= rt) return 0;
if (lt >= l && r >= rt) return t[ct];
int mt = (lt + rt) >> 1;
int lv = query(l, r, ct * 2 + 1, lt, mt);
int rv = query(l, r, ct * 2 + 2, mt, rt);
return lv + rv;
}
/// O(log n)
int query(int l, int r)
{
return query(l, r + 1, 0, 0, n);
}
/// O(log n)
/// Search: Min(x | Query(1, x) >= k)
int search_for(int k, int ct, int lt, int rt)
{
if (k > t[ct]) return -1;
if (rt - lt == 1) return lt;
int mt = (lt + rt) >> 1;
int v = t[ct * 2 + 1];
int res = search_for(k - 0, ct * 2 + 1, lt, mt);
if (res == -1)
res = search_for(k - v, ct * 2 + 2, mt, rt);
return res;
}
/// O(log n)
int search_for(int k)
{
return search_for(k, 0, 0, n);
}
/// O(log n)
/// Search: Min(x | x >= pos & Query(1, x) >= k)
int search_for_at_least(int pos, int k)
{
return search_for(k + query(1, pos - 1), 0, 0, n);
}
};
int main()
{
// file("Test");
ios::sync_with_stdio(NULL);
cin.tie(NULL);
/// Input: Number of element and steps
int n, k;
cin >> n >> k;
Segtree T;
T.init(n + 1);
for (int x = 1; x <= n; ++x) /// O(n log n)
T.modify(x, 1);
int pos = 1;
for (int remain = n; remain >= 1; --remain) /// O(n log n)
{
/// Number of steps
int step = k + 1;
/// Move move (remain) times remain the same pos
step %= remain;
if (step == 0) step = remain; /// Current pos my not the result, therefore move more (remain) steps
/// The current segment is not the part we need to search
int right = T.query(pos, n);
if (step > right)
{
pos = 1; /// Set it back to first pos
step -= right; /// Number of step traveled
}
/// Search for real pos
pos = T.search_for_at_least(pos, step);
T.modify(pos, 0);
cout << pos << " ";
}
return 0;
}
You can also use Iterative Segment Tree
/*
#Author: SPyofgame
#License: Free to use
*/
#include <iostream>
using namespace std;
const int N = 1 << 18;
int T[N+N];
void init(int n)
{
for (int i = 0; i < n; ++i) T[i + N] = 1;
for (int i = N - 1; i > 0; --i) T[i] = T[i << 1] + T[i << 1 | 1];
}
int lower_bound(int x, int p = 1)
{
while (p < N) if (T[p <<= 1] < x) x -= T[p++];
return p - N;
}
void update(int p, int v)
{
for (T[p += N] = v; p > 1; p >>= 1) T[p >> 1] = T[p] + T[p ^ 1];
}
int main()
{
int n, k;
cin >> n >> k;
init(n);
for (int remain = n, pos = 0; remain > 0; --remain)
{
pos += remain + k;
pos %= remain;
int p = lower_bound(pos + 1);
cout << p + 1 << " ";
update(p, 0);
}
return 0;
}

C++ Dynamic Programming: error in traversing the grid

Here's a question 8 from 2018 AIME Paper : A frog is positioned at the origin of the coordinate plane. From the point (x, y), the frog can jump to any of the points (x + 1, y), (x + 2, y), (x, y + 1), or (x, y + 2). Find the number of distinct sequences of jumps in which the frog begins at (0, 0) and ends at (x, y).
It felt that it can be solved using dynamic programming but my code seems to have an error which I cannot debug. This is how I approached the problem:
If f[i][j] denotes the number of ways to reach grid-point (i, j) from (0, 0) then
f[i][j] = f[i - 1][j] + f[i - 2][j] + f[j - 1][i] + f[j - 2][i]
and we have to assign values of f[][] for the base cases..
I don't think there's an issue with the logic. But the outputs are terrible.
Here's my code : https://ideone.com/lhhMUL
#include <bits/stdc++.h>
using namespace std;
int main() {
int n, x, y;
cin >> n >> x >> y;
int f[n][n];
f[0][1] = f[1][0] = 1;
f[0][2] = f[2][0] = 2;
f[1][2] = f[2][1] = 5;
for (int i = 2; i <= x - 1; i++) {
for (int j = 2; j <= y - 1; j++) {
f[i][j] = f[i - 1][j]
+ f[i - 2][j]
+ f[j - 1][i]
+ f[j - 2][i];
}
}
cout << f[y][x];
return 0;
}
Two bugs I see are
j and i are reversed in your recursion equation
Initial values of f (for example f[3][1] ) are never calculated. They are just random values of what was in memory when the arrays were allocated.
#include <bits/stdc++.h>
using namespace std;
int main()
{
int n,x,y; cin>>n>>x>>y;
int f[n][n];
f[0][0]=1;
f[1][0]=1;
f[0][1]=1;
f[1][1]=2;
for(int i = 2; i <= x; i ++ ) {
f[i][0] = f[i-1][0] + f[i-2][0];
}
for(int i = 2; i <= x; i ++ ) {
f[i][1] = f[i-1][1] + f[i-2][1] + f[i][0];
}
for(int j = 2; j <= y; j ++ ) {
f[0][j] = f[0][j-1] + f[0][j-2];
}
for(int j = 2; j <= y; j ++ ) {
f[1][j] = f[1][j-1] + f[1][j-2] + f[0][j];
}
for (int i=2; i<=x; i++)
for (int j=2; j<=y; j++) {
f[i][j]=f[i-1][j]+f[i-2][j]+f[i][j-1]+f[i][j-2];
// cout << i << " " << j << " " << f[i][j] << endl;
}
cout<< f[x][y];
return 0;
}

How to all possible ways in which any combination of n elements m times can be added to give a result

This is kind of an extension to this question:
Finding all possible combinations of numbers to reach a given sum
The difference is that in the above-linked question, each number(from the set of options) would be counted one time. But what if each number is allowed to be chosen multiple times? For example, if the given set of options is {1, 4, 9}, to get a total of 15, we can do any of the following:
a) 1*15
b) 4*3 + 1*2
c) 4*2 + 1*7
d) 4*1 + 1*11
e) 9*1 + 4*1 + 1*2
f) 9*1 + 1*6
Since you have asked all the possible combinations and not the best one so simple recursion can be used to obtain the results. The main idea is to:
1. Sort the array(non-decreasing).
2. First remove all the duplicates from array.
3. Then use recursion and backtracking to solve
A c++ solution for your problem:
#include <bits/stdc++.h>
using namespace std;
void getNumbers(vector<int>& ar, int sum, vector<vector<int> >& res,vector<int>& r, int i) {
if (sum < 0)
return;
if (sum == 0)
{
res.push_back(r);
return;
}
while (i < ar.size() && sum - ar[i] >= 0)
{
r.push_back(ar[i]);
getNumbers(ar, sum - ar[i], res, r, i);
i++;
r.pop_back();
}
}
vector<vector<int> > getSum(vector<int>& ar, int sum)
{
sort(ar.begin(), ar.end());
ar.erase(unique(ar.begin(), ar.end()), ar.end());
vector<int> r;
vector<vector<int> > res;
getNumbers(ar, sum, res, r, 0);
return res;
}
int main()
{
vector<int> ar;
ar.push_back(1);
ar.push_back(4);
ar.push_back(9);
int n = ar.size();
int sum = 15;
vector<vector<int> > res = getSum(ar, sum);
if (res.size() == 0)
{
cout << "Emptyn";
return 0;
}
for (int i = 0; i < res.size(); i++)
{
if (res[i].size() > 0)
{
cout << " ( ";
for (int j = 0; j < res[i].size(); j++)
cout << res[i][j] << " ";
cout << ")";
}
}
}

Need better algorithm for Sphere Online Judge's "FOODIES - ChickenLove" challenge

I'm trying to solve Sphere Online Judge's "FOODIES - ChickenLove" problem. In this problem, there are n sets of the form { 1, 2, …, A1 }, { 1, 2, …, A2 }, …, { 1, 2, …, An }. (The input just contains the integers A1, A2, … An; the other elements of the sets are implied.) The goal of the problem is, for a given m, to find the maximum sum that you can get by choosing m distinct elements from these sets.
For example, given this input:
A1 = 3 (meaning that the first set is { 1, 2, 3 })
A2 = 5 (meaning that the second set is { 1, 2, 3, 4, 5 })
A3 = 4 (meaning that the third set is { 1, 2, 3, 4 })
m = 3 (meaning that we need to select three elements from these sets)
the desired result is 4 + 4 + 5 = 13.
Currently I'm solving this with a priority queue, but I'm getting a "timeout" error (meaning that my solution takes too long). How can I optimize my solution? Is there a better approach?
MY CURRENT APPROACH
#include <bits/stdc++.h>
using namespace std;
int main()
{
int t;
scanf("%d",&t);
while(t--)
{
int n,k,x;
long long c=0;
scanf("%d",&n);
priority_queue<int> pq;
for(int i=0;i<n;i++)
{
scanf("%d",&x);
pq.push(x);
}
scanf("%d",&k);
for(int i=1;i<=k;i++)
{
int p=pq.top();
c+=p;
pq.push(p-1);
pq.pop();
}
printf("%lld\n",c);
}
return 0;
}
You are getting Time Limit Exceeded because the maximum M <= 10^10, and your code's time complexity is O(N + M log N).
This problem's constraints is 1 <= A[i] <= 100000, so you can count the number of x's in the all set (in my code: the value is c[x]).
So, you only have to process this queries for 1 <= i <= N. (initial value of c[i] = 0)
Add 1 to the values c[1], c[2], c[3],..., c[A[i]].
You can process with naive algorithm for O(M), and with cumulative-sum algorithm for O(N).
If you count c[1], c[2], ..., c[max(A[1], A[2],..., A[N])], you can do like my code:
#include <bits/stdc++.h>
using namespace std;
int T, N; long long M;
int main() {
scanf("%d", &T);
while(T--) {
scanf("%d", &N);
vector<int> A(N);
for(int i = 0; i < N; i++) scanf("%d", &A[i]);
scanf("%lld", &M);
int z = *max_element(A.begin(), A.end());
vector<int> c(z + 2), s(z + 2);
for(int i = 0; i < N; i++) s[1]++, s[A[i] + 1]--;
for(int i = 1; i <= z; i++) c[i] = c[i - 1] + s[i];
long long ret = 0;
for(int i = z; i >= 1; i--) {
if(M <= c[i]) {
ret += 1LL * M * i; M = 0;
break;
}
ret += 1LL * c[i] * i; M -= c[i];
}
printf("%lld\n", ret);
}
return 0;
}
The overall time complexity is O(N + max(A[1], A[2],..., A[N])).
I submitted to SPOJ and I got AC (0.20 sec) !

Uniform Cost search project euler #81

I am working on project euler programs for the sake of 'enlightenment' not just solving them. I have solved question 81 using dynamic progam on the 80x80 matrix but when I try to solve it using uniform cost search my program disappears into never land. I just want to know if this problem tractable using uniform cost search? The problem is available at this link.
UCS definitely works.
from Queue import PriorityQueue
with open('matrix.txt') as f:
data = map(lambda s: map(int, s.strip().split(',')), f.readlines())
seen = set()
pq = PriorityQueue()
pq.put((data[0][0], 0, 0))
while not pq.empty():
(s, i, j) = pq.get()
if (i, j) not in seen:
seen.add((i, j))
if i + 1 < len(data): pq.put((s + data[i + 1][j], i + 1, j))
if j + 1 < len(data[i]): pq.put((s + data[i][j + 1], i, j + 1))
if i + 1 >= len(data) and j + 1 >= len(data): print s
Here (as a reference) is a solution using Uniform-cost search in c++, compiled with -O2 takes less than a second on a i7 (without optimizations takes 3 secs):
#include <iostream>
#include <fstream>
#include <vector>
#include <set>
#include <algorithm>
using namespace std;
struct Node {
size_t i, j; int cost;
Node(size_t i, size_t j, int cost) : i(i), j(j), cost(cost) {}
};
bool operator<(const Node& a, const Node& b) { return b.cost < a.cost; }
bool operator==(const Node& a, const Node& b) { return a.i == b.i && a.j == b.j; }
int main() {
const size_t SIZE = 80;
ifstream fis("matrix.txt");
int matrix[SIZE][SIZE];
char crap;
for (size_t i = 0; i < SIZE; i++)
for (size_t j = 0; j < SIZE; j++) {
fis >> matrix[i][j];
if (j < SIZE - 1) fis >> crap;
}
vector<Node> open;
set<Node> closed;
open.push_back(Node(0, 0, matrix[0][0]));
make_heap(open.begin(), open.end());
while (!open.empty()) {
Node node = open.front();
pop_heap(open.begin(), open.end()); open.pop_back();
if (node.i == SIZE - 1 && node.j == SIZE - 1) {
cout << "solution " << node.cost << endl;
return 0;
}
closed.insert(node);
Node children[] = { Node(node.i + 1, node.j, node.cost + matrix[node.i + 1][node.j]),
Node(node.i, node.j + 1, node.cost + matrix[node.i][node.j + 1]) };
for (int k = 0; k < 2; k++) {
Node child = children[k];
if (!closed.count(child)) {
vector<Node>::iterator elem = find(open.begin(), open.end(), child);
if (elem == open.end()) {
open.push_back(child); push_heap(open.begin(), open.end());
} else if (child.cost < (*elem).cost) {
(*elem).cost = child.cost;
make_heap(open.begin(), open.end());
}
}
}
}
}
This solution would be little slow because it calls make_heap for element replacement in the open node list which rebuilds the heap in the vector, but shouldn't go to forever land and proves that the problem can be solved with UCS. A suggestion is to debug your solution using the base case given in Project Euler problem statement.

Resources