I need to calculate the sum of two diagonals in a matrix in C++, I already have a solution for that but I must be dumb because I cant understand what it is doing, so I would like to know if there is another version which I can understand. here is the code which does the job:
cout<<"Jepi rangun e matrices"<<endl; // pra bejme manipulim me matrice katrore ku rreshtat=kolonat
cin>>n;
cout<<"Tani jepi elementet e matrices"<<endl; // lexohet matrica
for(i=1;i<=n;i++)
{
for(j=1;j<=n;j++)
cin>>a[i][j];
}
d=0;
s=0; // ketu e keni kushtin si dhe mbledhjen per te dy diagonalet me dy variabla te ndryshme
for(i=1;i<=n;i++)
for(j=1;j<=n;j++)
{
if(i==j)
d=d+a[i][j];
if(j==n-i+1 || i==n-j+1)
s=s+a[i][j];
}
The part that is difficult to understand is
if(j==n-i+1 || i==n-j+1)
s=s+a[i][j];
Here is the entire code that I changed but it doesnt work for the secondary diagonal:
#include <iostream>
using namespace std;
int main()
{
int d=0,s=0; // ketu e keni kushtin si dhe mbledhjen per te dy diagonalet me dy variabla te ndryshme
int i,j,n;
int a[5][5];
cout<<"Jepi rangun e matrices"<<endl; // pra bejme manipulim me matrice katrore ku rreshtat=kolonat
cin>>n;
cout<<"Tani jepi elementet e matrices"<<endl; // lexohet matrica
for(i=1;i<=n;i++)
{
for(j=1;j<=n;j++)
cin>>a[i][j];
}
for(i=1;i<=n;i++)
{
for(j=1;j<=n;j++)
{
if(i==j)
d+=a[i][j]; //principal diagonal
if(i+j==n-1)
s+=a[i][j];//secondary diagonal
}
}
cout << d << endl;
cout << s << endl;
cin.get();
cin.get();
return 0;
}
It would be nice to have comments in English, but, the your code does (second loop):
browse all rows
browse all cells
if i == j (is in main diagonal):
increase one sum
if i == n - i + 1 (the other diagonal)
increase the second sum
The much nicer and much more effective code (using n, instead of n^2) would be:
for( int i = 0; i < n; i++){
d += a[i][i]; // main diagonal
s += a[i][n-i-1]; // second diagonal (you'll maybe need to update index)
}
This goes straight trough the diagonals (both at the one loop!) and doesn't go trough other items.
EDIT:
Main diagonal has coordinates {(1,1), (2,2), ..., (i,i)} (therefor i == j).
Secondary diagonal has coordinates (in matrix 3x3): {(1,3), (2,2),(3,1)} which in general is: {(1,n-1+1), (2, n-2+1), ... (i, n-i+1), .... (n,1)}. But in C, arrays are indexed from 0, not 1 so you won't need that +1 (probably).
All those items in secondary diagonal than has to fit condition: i == n - j + 1 (again due to C's indexing from 0 +1 changes to -1 (i=0,, n=3, j=2, j = n - i - 1)).
You can achieve all this in one loop (code above).
int diag1=0;
int diag2=0;
for (i=0;i<n;i++)
for (j=0;j<n;j++){
if(i==j) diag1+=a[i][j]; //principal diagonal
if(i+j==n-1) diag2+=a[i][j];//secondary diagonal
}
To understand this algorithm better you should paint a matrix on you notebook and number it's elements with their position in matrix,then apply the algorithm step by step.I'm 100% sure that you will understand
How about I try to explain this version? :D
There are 3 important parts of the code:
inputing the matrix
calculating major diagonal ( \ direction)
calculating minor diagonal ( / direction)
And here they are, explained:
// input elements
for(i=1;i<=n;i++) // from left to right
{
for(j=1;j<=n;j++) // from up to down
cin>>a[i][j]; // input element at (i,j) position
}
Here, d and s contain the inter-values of major and minor diagonal respectively. At the end of 2 loops, they will contain the results
for (i=1;i<=n;i++)
for (j=1;j<=n;j++)
{
if(i==j) // major diagonal - if coordinates are the same
d=d+a[i][j]; // e.g. (1,1), (2,2)
if(j==n-i+1 || i==n-j+1) // coordinates of the minor diagonal - check
s=s+a[i][j]; // e.g. n=3 (3,1) (2,2) ...
}
Hope this helps.
Note that this code starts matrix coordinates at 1 instead of 0, so you will actually need to allocate (n+1)x(n+1) space for the matrix:
double a[n+1][n+1];
before using it.
Also, the code you gave is not most effective. It has O(n^2) complexity, while the task can be done in O(n) like so:
// matrix coordinates now start from 0
for (int i=0; i < n; ++i){
d += a[i][i]; // major
s += a[i][n-1-i]; // minor
}
int num[5][5]={0}; //decleration
int i=0,j=0,sum=0;
for (int i=0;i<5;i++)
{
for (int j=0;j<5;j++)
{
cin>>num[i][j];
} //Taking Matrix input
}
cout<<endl<<"The Matrix is "<<endl;
for (int i=0;i<5;i++)
{
for (int j=0;j<5;j++)
{
cout<<num[i][j]<<" ";
}
cout<<endl; //Displaying the Matrix
}
cout<<endl<<"The sum of diagonals of the matrix is "<<endl;
if(i==j)
{
for (i=0;i<5;i++)
{
for (j=0;j<5;j++)
{
if (i==j) //This loop works where i and j will be equal
{
sum=sum+num[i][j];
}
}
}
cout<<sum;
}
else //Some times the user creates 4 x 3 matrix or so than diagonals not match so. . .
{
cout<<"The sum is not Possible";
}
you must use i + j == n + 1 instead of i + j == n - 1 for secondary diagonal i.e
for(i = 1; i <= n; i++)
{
for(j = 1; j <= n; j++)
{
if(i == j)
d += a[i][j]; //principal diagonal
if(i + j == n+1)
s += a[i][j];//secondary diagonal
}
}
Related
Given a square matrix mat[ ][ ] of size N x N. The task is to rotate it by 90 degrees in anti-clockwise direction without using any extra space. Problem Link
My Logic - for a matrix N x N, rotate the outer window in an anticlockwise direction by swapping elements starting from left column -> bottom row -> right column -> top row using temp variable X-1 time where X is the dimension of the outer window. I don't know why it's not working. Please Help me spot the problem.
#include<bits/stdc++.h>
using namespace std;
int main() {
int t=1; cin>>t;
while (t--) {
int n; cin>>n; vector<vector<int>>a(n,vector<int>(n));
for(int i=0;i<n;i++) for(int j=0;j<n;j++) cin>>a[i][j];
for(int k=0;k<n;k++) {
int i=k, j=0, p=n-1-k, q=p-i, temp;
while (q-- && i<p) {
temp=a[i][i];j=i;
while (j<=p) {
swap(temp, a[j][i]);j++;
}j=i+1;
while (j<=p) {
swap(temp, a[p][j]);j++;
}j=p-1;
while (j>=i) {
swap(temp, a[j][p]); j--;
}j=p-1;
while (j>=i) {
swap(temp, a[i][j]); j--;
}
}
}
for(int i=0;i<n;i++) {
for(int j=0;j<n;j++) cout<<a[i][j]<<" ";
cout<<"\n";
}
cout<<"\n";
}
}
Thank You
I would like to suggest an approach that looks more simpler.
Let's assume that you have a vector of vectors of the type char like this.
a b c d
e f g h
i j k l
m n o p
The result vector must look like
d h l p
c g k o
b f j n
a e i m
The result vector can be built in two steps.
In the first step the rows of the source vector are swapped.
m n o p
i j k l
e f g h
a b c d
In the second step there are swapped elements relative to the side diagonal that is for example 'm' is swapped with 'd', 'n' is swapped with 'h' and 'o' is swapped with 'l'. Then these operations are repeated for element of the second row the second column from the end of the vector.
Here is a demonstrative program.
#include <iostream>
#include <utility>
#include <vector>
int main()
{
std::vector<std::vector<char>> a =
{
{ 'a', 'b', 'c', 'd' },
{ 'e', 'f', 'g', 'h' },
{ 'i', 'j', 'k', 'l' },
{ 'm', 'n', 'o', 'p' },
};
auto n = a.size();
for ( const auto &row : a )
{
for ( const auto &item : row )
{
std::cout << item << ' ';
}
std::cout << '\n';
}
std::cout << '\n';
for ( size_t i = 0; i < n / 2; i++ )
{
std::swap( a[i], a[n-i-1] );
}
for ( const auto &row : a )
{
for ( const auto &item : row )
{
std::cout << item << ' ';
}
std::cout << '\n';
}
std::cout << '\n';
for ( size_t i = 0; i + 1 < n; i++ )
{
for ( size_t j = 0; j + i + 1 < n; j++ )
{
std::swap( a[i][j], a[n-j -1][n - i -1]);
}
}
for ( const auto &row : a )
{
for ( const auto &item : row )
{
std::cout << item << ' ';
}
std::cout << '\n';
}
std::cout << '\n';
return 0;
}
The program output is
a b c d
e f g h
i j k l
m n o p
m n o p
i j k l
e f g h
a b c d
d h l p
c g k o
b f j n
a e i m
[Note: my previous solution uses extra memory, this one doesn't. So, I've deleted the previous solution and totally updated it to provide the new one].
Well, this problem can be solved easily if we are able to use extra space, but that is not the case. Anyway, it can also be solved easily without using another extra space.
At first, let me explain my solution for this problem. Then, I'll tell you about the wrong doing in your code. My solution is similar to your approach. It considers the input array as layers of rings or loops. See below:
0 0 0 0 0
0 1 1 1 0
0 1 2 1 0
0 1 1 1 0
0 0 0 0 0
The outer ring is the 0's, the inner ring is the 1's and so on...
Now, for arguments sake, let's assume we're using extra space b(we won't use this space in solution though). Also, let us assume, b is the solved array that contains the rotated matrix. Then, we may say:
b[(n + n - j - 1) % n][i] = a[i][j] // for any i, j
// here "n" is dimension of matrix
// "i", represents ith indexed row of a
// "j", represents jth indexed column of a
// if you having problem, how this thing just dropped from sky, then
// just write down in paper, for some index (x, y) what it becomes when it is rotated
// you'll see some formula like I've described above
Okay, now, if you're clear with the formula, let me describe how this helps to solve problem:
In the previous ring figure(the one I've used for showing rings), you can see that the corner elements of the 0's rings just changed with each other, i.e. the corner elements just swap places with each other when the matrix rotated, they never interfere with other elements. This is also, true for other elements too. There is always four elements in a group, and they just swap position with each other! There's only one exception is the center(if n is odd). And the center never changes position...
If you've also, observed the loop/group of four elements, those just swap position with each other, then we can just find out the next element's position from present element's position and place the present element's value and we're done... So, how do find out next position's value. Notice, we've already talked about it, how b's result is calculated from a. So, we may write something below:
pair<int, int> getNext(pair<int, int> x, int n) {
return make_pair((n + n - x.second - 1) % n, x.first);
}
Now, come to rings, how many are there, that we should care about, well it's (n/2) rings. So, we'll just go to each ring, iterate through the elements of the first row of each ring(except the last one, cause it's included in the corner) and run a loop of four to replace the value properly in position. The full code is given below:
#include <iostream>
#include <string>
#define N 128
// returns next postition based on present position
// next position means where the present position value should
// be transferred after rotation
pair<int, int> getNext(pair<int, int> x, int n) {
return make_pair((n + n - x.second - 1) % n, x.first);
}
int main() {
int a[N][N];
int n;
scanf("%d", &n);
for(int i=0; i<n; i++) {
for(int j=0; j<n; j++) {
scanf("%d", &a[i][j]);
}
}
for(int h = 0; h < (n / 2); h++) {
int s = h;
int e = n - h - 1;
for(int k = s; k < e; k++) {
auto p = make_pair(s, k); // row = s, and col = k
int t = a[p.first][p.second];
for(int c=0; c<4; c++) {
auto p2 = getNext(p, n);
int temp = a[p2.first][p2.second];
a[p2.first][p2.second] = t;
t = temp;
p = p2;
}
}
}
for(int i=0; i<n; i++) {
for(int j=0; j<n; j++) {
printf("%d ", a[i][j]);
}
printf("\n");
}
return 0;
}
Now, what is wrong with your code:
I guess, you've already understood, that your algo is not correct...and the implementation is buggy too...
[P.S.]: pls, don't just copy paste the code, first understand it. Also, write code in a manner, so other's can read...and if any error you find with the algo I've provided or you may have problem with understanding any concept, let me know in the comment...
So I was solving this USACO 2013 February Silver Contest - Perimeter - Problem 1.
Link to the problem: Problem Link
Link to the bronze version of this problem: Problem Link
Link to solutions: Silver - Link to Solution Bronze - Link to Solution
The problem:
Problem 1: Perimeter [Brian Dean, 2013]
Farmer John has arranged N hay bales (1 <= N <= 50,000) in the middle of
one of his fields. If we think of the field as a 1,000,000 x 1,000,000
grid of 1 x 1 square cells, each hay bale occupies exactly one of these
cells (no two hay bales occupy the same cell, of course).
FJ notices that his hay bales all form one large connected region, meaning
that starting from any bale, one can reach any other bale by taking a
series of steps either north, south, east, or west onto directly adjacent
bales. The connected region of hay bales may however contain "holes" --
empty regions that are completely surrounded by hay bales.
Please help FJ determine the perimeter of the region formed by his hay
bales. Note that holes do not contribute to the perimeter.
PROBLEM NAME: perimeter
INPUT FORMAT:
Line 1: The number of hay bales, N.
Lines 2..1+N: Each line contains the (x,y) location of a single hay
bale, where x and y are integers both in the range
1..1,000,000. Position (1,1) is the lower-left cell in FJ's
field, and position (1000000,1000000) is the upper-right cell.
SAMPLE INPUT (file perimeter.in):
8
10005 200003
10005 200004
10008 200004
10005 200005
10006 200003
10007 200003
10007 200004
10006 200005
INPUT DETAILS:
The connected region consisting of hay bales looks like this:
XX
X XX
XXX
OUTPUT FORMAT:
Line 1: The perimeter of the connected region of hay bales.
SAMPLE OUTPUT (file perimeter.out):
14
OUTPUT DETAILS:
The length of the perimeter of the connected region is 14 (for example, the
left side of the region contributes a length of 3 to this total). Observe
that the hole in the middle does not contribute to this number.
What I did
I went ahead with a recursive solution to the problem which goes like this :
#include <iostream>
#include <cmath>
#include <vector>
#include <algorithm>
#include <map>
using namespace std;
#define rep(i,a,b) for(auto (i)=a;i<b;i++)
#define list(i,N) for(auto (i)=0;i<N;i++)
typedef long long ll;
typedef vector<ll> vi;
typedef pair<ll,ll> pi;
#define mp make_pair
#define pb push_back
#define int ll
#define INF 1e18+5
#define mod 1000000007
//One map for storing whether a cell has hay bale or not
//And the other for visited - whether a cell has been visited or not
map<pi,bool> vis;
map<pi,bool> exists;
int ans = 0;
void solve(int i, int j){
//Check about the visited stuff
if(vis[mp(i,j)]) return;
vis[mp(i,j)] = true;
//Find the answer now
ans += 4;
if(exists[mp(i-1,j)]){
--ans; solve(i-1,j);
}
if(exists[mp(i+1,j)]){
--ans; solve(i+1,j);
}
if(exists[mp(i,j+1)]){
--ans; solve(i,j+1);
}
if(exists[mp(i,j-1)]){
--ans; solve(i,j-1);
}
}
int32_t main(){
ios::sync_with_stdio(0);
cin.tie(0); cout.tie(0);
int N; cin >> N;
int first, second; //the starting point where we start the function...
while(N--){
int a,b; cin >> a >> b;
first = a; second = b; //in the end, it is just the coordinate specified in the last in the input...
exists[mp(a,b)] = true; //Hay Bale exists...
}
solve(first,second);
cout << ans << "\n";
return 0;
}
Basically, what I am doing is :
Start at a cell.
First, check if the cell has been previously visited. If yes, return. If not, make it visited.
Add 4 to the counter for all the four sides.
Look around the cell to all its neighbouring cells. If the cell also has haybales, subtract 1 from the counter (no need for adding boundary) and then goto 2.
The problem which I am facing
Observe that this code also counts the boundary required inside the hole. BUT we don't need to include that into our answer. I, however, don't know how to exclude that from our answer...
Why I mentioned the Bronze Problem
If you see the solution of the Bronze Problem (which is just the same problem but with different constraints), Mr Brian Dean also implements this sort of a recursive solution here which is similar to what I'm doing in my code. The code is down below :
#include <stdio.h>
#define MAX_N 100
int already_visited[MAX_N+2][MAX_N+2];
int occupied[MAX_N+2][MAX_N+2];
int perimeter;
int valid(int x, int y)
{
return x>=0 && x<=MAX_N+1 && y>=0 && y<=MAX_N+1;
}
void visit(int x, int y)
{
if (occupied[x][y]) { perimeter++; return; }
if (already_visited[x][y]) return;
already_visited[x][y] = 1;
if (valid(x-1,y)) visit(x-1,y);
if (valid(x+1,y)) visit(x+1,y);
if (valid(x,y-1)) visit(x,y-1);
if (valid(x,y+1)) visit(x,y+1);
}
int main(void)
{
int N, i, x, y;
freopen ("perimeter.in", "r", stdin);
freopen ("perimeter.out", "w", stdout);
scanf ("%d", &N);
for (i=0; i<N; i++) {
scanf ("%d %d", &x, &y);
occupied[x][y] = 1;
}
visit(0,0);
printf ("%d\n", perimeter);
return 0;
}
Why this solution does not work for the Silver
This is because the constraints in the Silver version of the problem which I'm solving has higher constraints but the same time limit. This times out the code.
So, I would be grateful if anybody could help me solve this problem in order to exclude the perimeter taken up by the hole in the middle.
Your solution is quite similar to the second one posted. But instead of walking on the bales, you walk on the perimeter:
void solve(int i, int j){
if(vis[mp(i,j)]) return;
if(exists[mp(i,j)]) return;
if(there_is_no_bale_next_to(i,j)) return; // consider all 8 directions
vis[mp(i,j)] = true;
ans ++;
solve(i-1,j);
solve(i+1,j);
solve(i,j+1);
solve(i,j-1);
}
You first run solve on a point definitely on perimeter(like the westmost point).
The problem with your solution is that it targets at the 'X' points, which will inevitably count the holes as well. Please consider to launch a floodfill that moves around the object without actually getting into it. My solution below implements this idea, so holes are not being counted. Brian Dean's solution in the official editorial is also based on this idea, so you should check out that as well.
#include<bits/stdc++.h>
using namespace std;
int n, ans = 0;
map<pair<int,int>, bool> m, vis;
pair<int,int> p = {INT_MAX, INT_MAX};
bool adj (int i, int j) {
for (int x = -1; x <= 1; x++) {
for (int y = -1; y <= 1; y++) {
if (!x & !y) continue;
if (m[{i + x, j + y}]) return true;
}
}
return false;
}
int get_cnt (int i, int j) {
int res = 0;
if (m[{i, j + 1}]) res++;
if (m[{i, j - 1}]) res++;
if (m[{i + 1, j}]) res++;
if (m[{i - 1, j}]) res++;
return res;
}
void floodfill (int i, int j) {
if (m[{i, j}] || vis[{i, j}] || !adj(i, j)) return;
vis[{i, j}] = true;
ans += get_cnt(i, j);
floodfill (i, j + 1);
floodfill (i, j - 1);
floodfill (i + 1, j);
floodfill (i - 1, j);
}
int main () {
cin >> n;
for (int i = 0; i < n; i++) {
int x, y;
cin >> x >> y;
m[{x, y}] = true;
p = min(p, {x, y});
}
floodfill (p.first - 1, p.second);
cout << ans << endl;
}
I am trying to calculate the determinant of a square matrix using row operations.
I ran into this code but I do not really understand how it works.
What do subi and subj do? Does it use row operations?
What is the logic behind this code?
int c, subi, i, j, subj;
double submat[10][10],d=0;
if (n == 2) {
return((mat[0][0] * mat[1][1]) - (mat[1][0] * mat[0][1]));
}
else {
for (c = 0; c < n; c++) {
subi = 0;
for (int i = 1; i < n; i++) {
subj = 0;
for (j = 0; j < n; j++) {
if (j == c)
continue;
submat[subi][subj] = mat[i][j];
subj++;
}
subi++;
}
d = d + (pow(-1, c)*mat[0][c] * determinant(n - 1, submat));
}
}
return d;
The function, which looks like:
double determinant(int n, double mat[10][10]);
recursively goes through rows and calls itself on the submatrices for that row and the first column return a value for all by matrices. The recursion ends for 2 by 2 matrices.
This is a recursive function using Laplace expansion to calculate the determinant whose base case is a 2 by 2 matrix.
However, it does not seem to be a good program to me for:
what if the input is a 1 by 1 matrix
submat is limited by size of 10 by 10
submat is a waste of memory
When matrix is large, it is better to use LU decomposition.
Problem description:
There's a chocolate bar that consists of m x n squares. Some of the squares are black, some are white. Someone breaks the chocolate bar along its vertical axis or horizontal axis. Then it is broken again along its vertical or horizontal axis and it's being broken until it can broken into a single square or it can broken into squares that are only black or only white. Using a preferably divide-and-conquer algorithm, find the number of methods a chocolate bar can be broken.
Input:
The first line tells you the m x n dimensions of the chocolate bar. In the next m lines there are n characters that tell you how does the chocolate bar look. Letter w is a white square, letter b is a black square.
for example:
3 2
bwb
wbw
Output:
the number of methods the chocolate bar can be broken:
for the example above, it's 5 (take a look at the attached picture).
I tried to solve it using an iterative approach. Unfortunately, I couldn't finish the code as I'm not yet sure how to divide the the halves (see my code below). I was told that an recursive approach is much easier than this, but I have no idea how to do it. I'm looking for another way to solve this problem than my approach or I'm looking for some help with finishing my code.
I made two 2D arrays, first for white squares, second for black squares. I'm making a matrix out of the squares and if there's a chocolate of such or such color, then I'm marking it as 1 in the corresponding array.
Then I made two arrays of the two cumulative sums of the matrices above.
Then I created a 4D array of size [n][m][n][m] and I made four loops: first two (i, j) are increasing the size of an rectangular array that is the size of the searching array (it's pretty hard to explain...) and two more loops (k, l) are increasing the position of my starting points x and y in the array. Then the algorithm checks using the cumulative sum if in the area starting at position kxl and ending at k+i x l+j there is one black and one white square. If there is, then I'm creating two more loops that will divide the area in half. If in the two new halves there are still black and white squares, then I'm increasing the corresponding 4D array element by the number of combinations of the first halve * the number of combinations of the second halve.
#include <iostream>
#include <fstream>
using namespace std;
int main()
{
int counter=0;
int n, m;
ifstream in;
in.open("in.txt");
ofstream out;
out.open("out.txt");
if(!in.good())
{
cout << "No such file";
return 0;
}
in >> n >> m;
int whitesarray[m][n];
int blacksarray[m][n];
int methodsarray[m][n][m][n];
for(int i=0; i<m; i++)
{
for(int j=0; j<n; j++)
{
whitesarray[i][j] = 0;
blacksarray[i][j] = 0;
}
}
while(in)
{
string colour;
in >> colour;
for (int i=0; i < colour.length(); i++)
{
if(colour[i] == 'c')
{
blacksarray[counter][i] = 1;
}
if(colour[i] == 'b')
{
whitesarray[counter][i] = 1;
}
}
counter++;
}
int whitessum[m][n];
int blackssum[m][n];
for (int i=0; i<m; i++)
{
for (int j=0; j<n; j++)
{
if(i-1 == -1 && j-1 == -1)
{
whitessum[i][j] = whitesarray[i][j];
blackssum[i][j] = blacksarray[i][j];
}
if(i-1 == -1 && j-1 != -1)
{
whitessum[i][j] = whitessum[i][j-1] + whitesarray[i][j];
blackssum[i][j] = blackssum[i][j-1] + blacksarray[i][j];
}
if(j-1 == -1 && i-1 != -1)
{
whitessum[i][j] = whitessum[i-1][j] + whitesarray[i][j];
blackssum[i][j] = blackssum[i-1][j] + blacksarray[i][j];
}
if(j-1 != -1 && i-1 != -1)
{
whitessum[i][j] = whitessum[i-1][j] + whitessum[i][j-1] - whitessum[i-1][j-1] + whitesarray[i][j];
blackssum[i][j] = blackssum[i-1][j] + blackssum[i][j-1] - blackssum[i-1][j-1] + blacksarray[i][j];
}
}
}
int posx=0;
int posy=0;
int tempwhitessum=0;
int tempblackssum=0;
int k=0, l=0;
for (int i=0; i<=m; i++)
{
for (int j=0; j<=n; j++) // wielkosc wierszy
{
for (posx=0; posx < m - i; posx++)
{
for(posy = 0; posy < n - j; posy++)
{
k = i+posx-1;
l = j+posy-1;
if(k >= m || l >= n)
continue;
if(posx==0 && posy==0)
{
tempwhitessum = whitessum[k][l];
tempblackssum = blackssum[k][l];
}
if(posx==0 && posy!=0)
{
tempwhitessum = whitessum[k][l] - whitessum[k][posy-1];
tempblackssum = blackssum[k][l] - blackssum[k][posy-1];
}
if(posx!=0 && posy==0)
{
tempwhitessum = whitessum[k][l] - whitessum[posx-1][l];
tempblackssum = blackssum[k][l] - blackssum[posx-1][l];
}
if(posx!=0 && posy!=0)
{
tempwhitessum = whitessum[k][l] - whitessum[posx-1][l] - whitessum[k][posy-1] + whitessum[posx-1][posy-1];
tempblackssum = blackssum[k][l] - blackssum[posx-1][l] - blackssum[k][posy-1] + blackssum[posx-1][posy-1];
}
if(tempwhitessum >0 && tempblackssum > 0)
{
for(int e=0; e<n; e++)
{
//Somehow divide the previously found area by two and check again if there are black and white squares in this area
}
for(int r=0; r<m; r++)
{
//Somehow divide the previously found area by two and check again if there are black and white squares in this area
}
}
}
}
}}
return 0;
}
I strongly recommend recursion for this. In fact, Dynamic Programming (DP) would also be very useful, especially for larger bars. Recursion first ...
Recursion
Your recursive routine takes a 2-D array of characters (b and w). It returns the number of ways this can be broken.
First, the base cases: (1) if it's possible to break the given bar into a single piece (see my comment above, asking for clarification), return 1; (2) if the array is all one colour, return 1. For each of these, there's only one way for the bar to end up -- the way it was passed in.
Now, for the more complex case, when the bar can still be broken:
total_ways = 0
for each non-edge position in each dimension:
break the bar at that spot; form the two smaller bars, A and B.
count the ways to break each smaller bar: count(A) and count(B)
total_ways += count(A) * count(B)
return total_ways
Is that clear enough for the general approach? You still have plenty of coding to do, but using recursion allows you to think of only the two basic ideas when writing your function: (1) How do I know when I'm done, and what trivial result do I return then? (2) If I'm not done, how do I reduce the problem?
Dynamic Programming
This consists of keeping a record of situations you've already solved. The first thing you do in the routine is to check your "data base" to see whether you already know this case. If so, return the known result instead of recomputing. This includes the overhead of developing and implementing said data base, probably a look-up list (dictionary) of string arrays and integer results, such as ["bwb", "wbw"] => 5.
I was solving problems on HackerRank when I got stuck at this one.
Problem Statement
You are given a 2D matrix, a, of dimension MxN and a positive integer R. You have to rotate the matrix R times and print the resultant matrix. Rotation should be in anti-clockwise direction.
Rotation of a 4x5 matrix is represented by the following figure. Note that in one rotation, you have to shift elements by one step only (refer sample tests for more clarity).
It is guaranteed that the minimum of M and N will be even.
Input
First line contains three space separated integers, M, N and R, where M is the number of rows, N is number of columns in matrix, and R is the number of times the matrix has to be rotated.
Then M lines follow, where each line contains N space separated positive integers. These M lines represent the matrix.
Output
Print the rotated matrix.
Constraints
2 <= M, N <= 300
1 <= R <= 10^9
min(M, N) % 2 == 0
1 <= aij <= 108, where i ∈ [1..M] & j ∈ [1..N]'
What I tried to do was store the circles in a 1D array. Something like this.
while(true)
{
k = 0;
for(int j = left; j <= right; ++j) {temp[k] = a[top][j]; ++k;}
top++;
if(top > down || left > right) break;
for(int i = top; i <= down; ++i) {temp[k] = a[i][right]; ++k;}
right--;
if(top > down || left > right) break;
for(int j = right; j >= left; --j) {temp[k] = a[down][j] ; ++k;}
down--;
if(top > down || left > right) break;
for(int i = down; i >= top; --i) {temp[k] = a[i][left]; ++k;}
left++;
if(top > down || left > right) break;
}
Then I could easily rotate the 1D matrix by calculating its length modulo R. But then how do I put it back in matrix form? Using a loop again would possibly cause a timeout.
Please don't provide code, but only give suggestions. I want to do it myself.
Solution Created :
#include <iostream>
using namespace std;
int main() {
int m,n,r;
cin>>m>>n>>r;
int a[300][300];
for(int i = 0 ; i < m ; ++i){
for(int j = 0; j < n ; ++j)
cin>>a[i][j];
}
int left = 0;
int right = n-1;
int top = 0;
int down = m-1;
int tleft = 0;
int tright = n-1;
int ttop = 0;
int tdown = m-1;
int b[300][300];
int k,size;
int temp[1200];
while(true){
k=0;
for(int i = left; i <= right ; ++i)
{
temp[k] = a[top][i];
// cout<<temp[k]<<" ";
++k;
}
++top;
if(top > down || left > right)
break;
for(int i = top; i <= down ; ++i)
{
temp[k]=a[i][right];
// cout<<temp[k]<<" ";
++k;
}
--right;
if(top > down || left > right)
break;
for(int i = right; i >= left ; --i)
{
temp[k] = a[down][i];
// cout<<temp[k]<<" ";
++k;
}
--down;
if(top > down || left > right)
break;
for(int i = down; i >= top ; --i)
{
temp[k] = a[i][left];
// cout<<temp[k]<<" ";
++k;
}
++left;
if(top > down || left > right)
break;
//________________________________\\
size = k;
k=0;
// cout<<size<<endl;
for(int i = tleft; i <= tright ; ++i)
{
b[ttop][i] = temp[(k + (r%size))%size];
// cout<<(k + (r%size))%size<<" ";
// int index = (k + (r%size))%size;
// cout<<index;
++k;
}
++ttop;
for(int i = ttop; i <= tdown ; ++i)
{
b[i][tright]=temp[(k + (r%size))%size];
++k;
}
--tright;
for(int i = tright; i >= tleft ; --i)
{
b[tdown][i] = temp[(k + (r%size))%size];
++k;
}
--tdown;
for(int i = tdown; i >= ttop ; --i)
{
b[i][tleft] = temp[(k + (r%size))%size];
++k;
}
++tleft;
}
size=k;
k=0;
if(top != ttop){
for(int i = tleft; i <= tright ; ++i)
{
b[ttop][i] = temp[(k + (r%size))%size];
++k;
}
++ttop;
}
if(right!=tright){
for(int i = ttop; i <= tdown ; ++i)
{
b[i][tright]=temp[(k + (r%size))%size];
++k;
}
--tright;
}
if(down!=tdown){
for(int i = tright; i >= tleft ; --i)
{
b[tdown][i] = temp[(k + (r%size))%size];
++k;
}
--tdown;
}
if(left!=tleft){
for(int i = tdown; i >= ttop ; --i)
{
b[i][tleft] = temp[(k + (r%size))%size];
++k;
}
++tleft;
}
for(int i = 0 ; i < m ;++i){
for(int j = 0 ; j < n ;++j)
cout<<b[i][j]<<" ";
cout<<endl;
}
return 0;
}
You need to break down this problem (remind me of an interview question from gg and fb) :
Solve first rotating a sequence one a single position
Then solve rotating a sequence N times
Model each "circle" or ring as an array. You may or may not actually need to store in a separate data
Iterate over each ring and apply the rotating algorithm
Lets consider the case of an array of length L which needs to be rotated R time. Observe that if R is a multiple of L, the array will be unchanged.
Observe too that rotating x times to the right is the same as rotating L - x to the left (and vice versa).
Thus you can first design an algorithm able to rotate once either left or right one exactly one position
Reduce the problem of rotating R times to the left to rotating R modulo L to the left
If you want to go further reduce the problem of rotating R modulo L to the left to rotating left R modulo L or rotating right L - R modulo L. Which means if you have 100 elements and you have to do 99 rotations left, you better do 1 rotation right and be done with it.
So the complexity will be O ( Number of circles x Circle Length x Single Rotation Cost)
With an array in-place it means O( min(N,m) * (N * M)^2 )
If you use a doubly linked list as temporary storage, a single rotation sequence is done by removing the front and putting it at the tail (or vice versa to rotate right). So what you can do is copy all data first to a linked list. Run the single rotation algorithm R modulo L times, copy back the linked list on the ring position, and move on the next right till all rings are processed.
Copy ring data to list is O(L), L <= N*M
Single Rotation Cost is O(1)
All rotations R modulo L is O(L)
Repeat on all min(N,m) rings
With a spare double linked list it means complexity of O( min(N,m) * (N * M))
I would start with a simplifying assumption: M is less than or equal to N. Thus, you are guaranteed to have an even number of rows. (What if M > N? Then transpose the matrix, carry out the algorithm, and transpose the matrix again.)
Because you have an even number of rows, you can easily find the corners of each cycle within the matrix. The outermost cycle has these corners:
a1,1 → aM,1 → aM,N → a1,N
To find the next cycle, move each corner inward, which means incrementing or decrementing the index at each corner as appropriate.
Knowing the sequence of corners allows you to iterate over each cycle and store the values in a one-dimensional vector. In each such vector a, start from index R % a.size() and increment the index a.size() - 1 times to iterate over the rotated elements of the cycle. Copy each element a[i % a.size()] back to the cycle.
Note that we don't actually rotate the vector. We accomplish the rotation by starting from an offset index when we copy elements back to the matrix. Thus, the overall running time of the algorithm is O(MN), which is optimal because it costs O(MN) just to read the input matrix.
I would treat this as a problem that divides the matrix into submatrices. You could probably write a function that shifts the matrices (and submatrices) outer rows and columns by one each time you call it. Take care to handle the four corners of the matrix appropriately.
Check this out for suggestions how to shift the columns.
Edit (more detailed):
Read each matrix circle in as a vector, use std::rotate on it R % length.vector times, write back. Maximally 150 operations.
Each element moves uniquely according to one of four formulas, adding five movements of known sizes (I'll leave the size calculation out since you wanted to figure it out):
formula (one of these four):
left + down + right + up + left
down + right + up + left + down
right + up + left + down + right
up + left + down + right + up
Since the smallest side of the matrix is even, we know there is not an element remaining in place. After R rotations, the element has circled around floor (R / formula) times but still needs to undergo extra = R % formula shifts. Once you know extra, simply calculate the appropriate placement for the element.