I got the task where I must find the H shaped region which has the biggest sum of numbers in it. Under 'H' shaped region, tha task meant this, consisting of 7 elements and never changing:
x x
xxx
x x
The matrix's size must be 33 or bigger than that, and I don't have to work with rotated 'H' shape. However, it can move upwards and downwards if the matrix is that big (for example a 46 matrix).
I thought of first counting a "maximum" value, starting from the [0][0] element. However, I can't figure out how to move this region-counting along. Could you help me out, please?
Here's my code so far:
#include<iostream>
int main(){
int n = 3;
int m = 4;
int mtx[n][m] = {
1,1,1,3,
1,1,1,3,
1,1,1,3
};
//counting the maximum H value
int max = 0;
for(int i = 0; i < n; i++){
max += mtx[i][0];
}
for(int i = 0; i < n; i++){
max += mtx[i][2];
}
max += mtx[1][1];
int counter = 0;
int j = 0;
int k = 0;
//finding if there is bigger
while(counter >max){
//questioned area, not sure what to do here
if(counter < max){
max = counter;
}
}
return 0;
}
As mentioned in a comment, knowing the single maximum element in the matrix does not help to find the maximum H shape. A concrete counter example:
0 1 0 5
9 1 1 5
0 1 0 5
Maximum element is 9 but maximum sum H shape is
1 0 5
1 1 5
1 0 5
You would need to add more information to know whether the maximum element is part of the maximum H: Only if max_element + 6*min_element > 7*second_smallest_element you can be sure that max_element is part of the biggest sum H. This condition could be refined, but it cannot be made such that the biggest element is always part of the biggest sum H, because thats not true in general (see counter example above).
As suggested in another comment, you should write a function that given coordinates of the upper left corner calculates the sum of elements in the H shape:
#include <iostream>
#include <array>
int H_sum(const std::array<std::array<int,4>,3>& matrix, int x0,int y0){
// A E
// BDF
// C G
int sum = matrix[x0][y0]; // A
sum += matrix[x0+1][y0]; // B
sum += matrix[x0+2][y0]; // C
sum += matrix[x0+1][y0+1]; // D
sum += matrix[x0][y0+2]; // E
sum += matrix[x0+1][y0+2]; // F
sum += matrix[x0+2][y0+2]; // G
return sum;
}
int main() {
std::array<std::array<int,4>,3> mtx{
1,1,1,3,
1,1,1,3,
1,1,1,3
};
for (const auto& row : mtx){
for (const auto& e : row){
std::cout << e;
}
std::cout << "\n";
}
std::cout << H_sum(mtx,0,0);
}
This is of course only something to get you started. Next you have to carefully consider what are the maximum indices you can pass to H_sum without going out-of-bounds. Then write a nested loop to scan all positions of the H and remember the maximum value encountered.
Last but not least, what I described so far is a brute force approach. You calculate sum for all possible H shapes, remember the maximum, and are done. Maybe there is a clever trick to avoid adding all elements multiple times (for example in a larger matrix, the right leg of one H is the left leg of a different H). Though before applying such tricks and trying to be clever I strongly suggest to write something that is perhaps slow but correct, easy to read and verify.
Related
The problem I am trying to solve is the following: I get N rectangular paper strips with 1cm width and length C. I need to cut the strips at a height where the sum of the areas of the cut strip is equal to A. You can see an example bellow for which N = 5, the strips are of length, 5,3,6,2 and 3 cm and A = 3cm where the cut is made at 4cm.
Note that I'm looking here for the red area.
The input is given as follows. The first line in each case begins with two integers N (1 ≤ N ≤ 10^5) and A (1 ≤ A ≤ 10^9) representing respectively the number of strips and the expected resulting area. The next line contains N integers, representing the length C_i (1 <= C_i <= 10^4) of each strip.
The input ends with A = C = 0, which should not be processed.
For each test case, output a single line, the height H of the cut that must be done so that the sum of the area of the cut strips is equal to A cm². Print the answer with 4 decimal places. Output ":D" if no cutting is required, or "-.-" if it’s impossible.
This problem can be found here
My idea for solving this problem was to use a binary search where I pick a height in the middle of the strips and make it larger or smaller depending on whether my cut was too high or too low. My implementation of the problem is given bellow:
#include <iostream>
#include <vector>
#include <iomanip>
#include <algorithm>
using namespace std;
int main(){
vector<int> v; // Vector that holds paper heights
int n; // Number of papers
double h, // Height of the cut
sum, // Area sum
min_n, // Minimum height for cut to happen
max_n, // Maximum height for cut to happen
a; // Desired final area
// Set desired output
cout << fixed << setprecision(4);
/* Get number of papers and desired area,
terminates if N = A = 0
*/
while(cin >> n >> a && (n||a)){
v.resize(n); // Resize vector to fit all papers
// Get all paper sizes
for(int i=0;i<n;i++){
cin >> v[i];
}
/* Sort the vector in decreasing order to
simplify the search
*/
sort(v.begin(),v.end(),greater<int>());
max_n = v[0]; // Largest possible cut is at the height of the largest paper
min_n = 0; // Smallest possible cut is at the base with height 0
// Iterate until answer is found
while(true){
// Initialize cut height as the average of smallest and largest cut sizes
h = (min_n + max_n)/2;
/* The area sum is equal to the sum of the areas of each cut, which is
given by the height of the paper minus the cut height. If the cut is
higher than the paper, the cut has area 0.
*/
sum = 0;
// Using mascoj sugenstion, a few changes were added
int s; // Temporary variable to hold number of time h is subtracted
for(int i=0; i<n;i++){
if(v[i] <= h) break; // From here onward cut area is 0 and there is no point adding
sum += v[i]; // Removed the subtraction inside of the for loop
s++; // Count how many paper strips were used
}
sum -= h*s // Subtracts the area cut from the s paper strips
// If the error is smaller than the significant value, cut height is printed
if(std::abs(sum-a) < 1e-5){
// If no cut is needed print :D else print cut height
(h < 1e-4 ? cout << ":D" << endl : cout << h << endl);
break;
}
// If max_n is "equal" to min_n and no answer was found, there is no answer
else if(max_n - min_n < 1e-7){
cout << "-.-" << endl;
break;
}
// Reduces search interval
sum < a ? max_n = h : min_n = h;
}
}
return 0;
}
The problem is, after submitting my answer I keep getting a 10% error. The website has a tool for comparing the output of you program with the expected output so I ran a test file with over 1000 randomly generated test cases and when I compared both I got a rounding error on the 4th decimal case, unfortunately, I don't have the file nor the script to generate test cases for me anymore. I tried changing the acceptable error to a smaller one but that didn't work. I can't seem to find the error, does any of you have an idea of what is happening?
ps: Although the problem doesn't say on the description, you can get cuts with fractions as heights
Might be your problem, maybe not: This line is exacerbating floating point error: sum += v[i]-h;
Floating points are only so accurate and compounding this error over a larger summation adds up. I would try using multiplication on h and subtracting that from the total sum of applicable lengths. Should be well within the range of the double precision format so I wouldn't worry about overrunning the format.
Not sure to understand your algorithm but I think that can be done a lot simpler using a map instead a vector.
In the following example the map mp memorize how much (the value) strips are of a given lenght (the key).
An advantage of the map is ordered.
Next you can see how much you have to save (not to cat) and calculate the level of the cut starting from zero, adding 1 when appropriate and adding a fraction when neccessary.
Hope the following example can help
#include <map>
#include <iomanip>
#include <iostream>
int main()
{
int n;
int n2;
int v;
int cut;
int a;
std::map<int, std::size_t> mp;
long long int sum;
long long int ts;
std::cout << std::fixed << std::setprecision(4);
while( (std::cin >> n >> a) && ( n || a ) )
{
mp.clear();
n2 = 0;
sum = 0LL;
for ( auto i = 0 ; i < n ; ++i )
{
std::cin >> v;
if ( v > 0 )
{
sum += v;
++mp[v];
++n2;
}
}
// mp is a map, so the values are ordered
// ts is "to save"; sum of lenghts minus a
ts = sum - a;
// cut level
cut = 0;
// while we can add a full cm to the cut level
while ( (ts > 0LL) && (n2 > 0) && (ts >= n2) )
{
++cut;
ts -= n2;
if ( cut >= mp.cbegin()->first )
{
n2 -= mp.cbegin()->second;
mp.erase(mp.cbegin());
}
}
if ( (ts == 0LL) && (cut == 0) )
std::cout << ":D" << std::endl; // no cut required (?)
else if ( n2 == 0 )
std::cout << "-.-" << std::endl; // impossible (?)
else
std::cout << (cut + double(ts) / n2) << std::endl;
}
}
p.s.: observe that a is defined as an integer in the page that you link.
I have a simple problem.
I am having an array A[] of N numbers. I have to perform this operarion:
for(i = 2; i<=N; i++)
A[i] = A[i] + A[i-1]
to the array A[] k times. And after performing this operation k times, I have to output the Xth index element.
Doing it with brute force, will lead to TLE.
I was searching for some pattern, but, I came to a solution which is not perfect as it needs to be.
Can you please help me, to find some more efficient solution to this problem.
I have an example, to clear the question.
Let's say array A is [1,2,3] and I need to perform the above operation 3 times then:
Array after 1st turn: A=[1,3,6]
Array after 2nd turn: A=[1,4,10]
Array after 3rd turn: A=[1,5,15]
So, if I am required to find the 2nd element of the array now, then it would be 5.
I you look to the Pascal's triangle (as #MBo say) you may notice that after k times the number of times each number get added in the final result is equal to a square in the triangle following the diagonals. Let see an example here:
This image correspond to iterate four times for the first three elements. So, as you can see if we have as input k equal to the number of times and n equal to the index of the element to return, all we have to do is multiply each of the numbers in the diagonal filled in blue until the red line (the image configuration correspond to k = 4 and n = 2).
After that, we have this formula:
Now, to improve the way we calculate the formula show above, we can use dynamic programming and calculate the factorial function from 0 ... k+n (note that the bigger number in the sequence is k-1+n). With this we can access to factorial(n) in a constant time. Also if we expand the combinatoric factor inside the summation we notice that the factor (k - 1 + i - i)! = (k - 1)! so, we can put this outside the summation.
Here is the code:
#include "stdafx.h"
#include "iostream"
using namespace std;
int findingXth(int a[], int n, int k, int factorial[]){
if (k == 0)
return a[n];
int result = 0;
for (int i = 0; i <= n; ++i)
{
int up = k - 1 + i;
result += (factorial[up] / factorial[i]) * a[n - i];
}
return result / factorial[k - 1];
}
int main(int argc, _TCHAR* argv[])
{
int a[3] = { 1, 2, 3 };
int n = 2;
int k = 3;
int factorial[100000]; // probably the expecification of the problem has some upper bounds for n and k (the length of the factorial array can be set to n+k+1);
factorial[0] = 1;
for (int i = 1; i < n + k; i++)
{
factorial[i] = factorial[i - 1] * i;
}
int result = findingXth(a, n, k, factorial);
std::cout << result;
return 0;
}
In a recent problem where i have to sum all values at common indexes in all possible subsets of size k in array of size n.
For eg: If
array ={1,2,3}
Its subsets (k=2) will be (x [i] , x [j]) where i < j
1 2
1 3
2 3
Sum:4,8
Firstly I have used recursion (same that of generating all subsets)
int sum_index[k]={0};
void sub_set(int array[],int n,int k,int temp[],int q=0,int r=0)
{
if(q==k)
{
for(int i=0;i<k;i++)
sum_index[i]+=temp[i];
}
else
{
for(int i=r;i<n;i++)
{
temp[q]=array[i];
sub_set(value,n,k,temp,q+1,i+1);
}
}
}
Problem is its taking too much time then expected .
Then i modified it to...
void sub_set(int array[],int n,int k,int temp[],int q=0,int r=0)
{
if(q==k)
{
return;
}
else
{
for(int i=r;i<n;i++)
{
temp[q]=array[i];
sum_index[q]+=temp[q]; //or sum_index[q]+=s[i];
sub_set(value,n,k,temp,q+1,i+1);
}
}
}
Still taking too much time!!
Is there any other approach to this problem?? Or any other modification i needed that i am unaware of??
Instead of iterating through the possible sub-sets, think of it a combinatorics problem.
To use your example of k=2 and {1,2,3}, let's just look at the first value of the result. It has two 1's and one 2. The two 1's correspond to the number one element sets that can be made from {2, 3} and the one 2 corresponds to the number of one element sets that can be made from {3}. A similar arrangement exists for the one 2 and two 3's in the second element of the result and looking at the subsets of the elements that appear before the element being considered.
Things get a bit more complicated when k>2 because then you will have to look for the number of combinations of elements before and after the element being considered, but the basic premise still works. Multiply the number of possible subsets before times the number of subsets afterwards and that will tell you how many times each element contributes to the result.
A solution in O(n^2) instead of O(n!):
First a tiny (:)) bit of explanation, then some code:
I´m going to assume here that your array is sorted (if not, use std::sort first). Additionally, I´m going to work with the array values 1,2,3,4... here, if you array consists arbitrary values (like 2 8 17), you´ll have to think of it as the indices (ie. 1=>2, 2=>8 etc.)
Definition: (x choose y) means the binomial coefficient, how it is calculated is in the link too. If you have an array size a and some k for the subset size, (a choose k) is the number of permutations, eg. 3 for your example: (1,2), (1,3) and (2,3).
You want the sum for each column if you write the permutations under each other, this would be easy if you knew for each column how many times each array element occurs, ie. how many 1´s, 2´s and 3´s for the first, and how many for second column (with k=2).
Here a bigger example to explain: (1,2,3,4,5) and all possible k´s (each in one block):
1
2
3
4
5
12
13
14
15
23
24
25
34
35
45
123
124
125
134
135
145
234
235
245
345
... (didn´t write k=4)
12345
Let´s introduce column indices, 0<=c<k, ie. c=0 means the first column, c=1 the second and so on; and the array size s=5.
So, looking eg. at the k=3-block, you´ll notice that the lines beginning with 1 (column c=0) have all permutations of the values (2,3,4,5) for k=2, more generally a value x in column c has all permutations for values x+1 to s after it. The values from from x+1 to s are s-x different values, and after column c there are k-c-1 more columns. So, for a value x, you can calculate ((s-x) choose (k-c-1)).
Additionally, the first column has only the values 1,2,3, the last two numbers are not here because after this column there are two more columns.
If you do this for the first column, it works well. Eg. with value 1 in the first column of k=3 above:
count(x) = ((s-x) choose (k-c-1)) = (4 choose 2) = 6
and indeed there are six 1 there. Calculate this count for every array value, multiply x*count(x), and sum it up for every x, that´s the result for the first column.
The other columns are a tiny bit harder, because there can be multiple "permutation blocks" of the same number. To start with, the step above needs a small adjustment: You need a muliplier array somewhere, one multiplier for each array value, and in the beginning each multiplier is 1. In the calculation x*count(x) above, take x*count(x)*muliplier(x) instead.
In the k=3-example, 1 in the first column can be followed by 2,3,4, 2 can be followed by 3,4, and 3 by 4. So the 3-based permutations of the second column need to be counted twice, and the 4-based even three times; more generally so many times like there are smaller values in the previos colums. Multiply that to the current multiplier.
...
Some code:
#include<iostream>
#include<vector>
#include<algorithm>
using namespace std;
// factorial (x!)
unsigned long long fact(unsigned char x)
{
unsigned long long res = 1;
while(x)
{
res *= x;
x--;
}
return res;
}
//binomial coefficient (n choose k)
unsigned long long binom(unsigned char n, unsigned char k)
{
if(!n || !k) return 1;
return (fact(n) / fact(k)) / fact(n-k);
}
//just for convenience
template<class T> void printvector(std::vector<T> data)
{
for(auto l : data) cout << l << " ";
cout << endl;
}
std::vector<unsigned long long> calculate(std::vector<int> data, int k)
{
std::vector<unsigned long long> res(k, 0); //result data
std::vector<unsigned long long> multiplier(data.size(), 1);
if(k < 1 || k > 255 || data.size() < 1) return res; //invalid stuff
std::sort(data.begin(), data.end()); //as described
for(int column = 0; column < k; column++) //each column separately
{
//count what to multiply to the multiplier array later
std::vector<unsigned long long> newmultiplier(data.size(), 0);
//for each array element in this column
for(int x = column; x <= (data.size() + column - k); x++)
{
//core calculation
res[column] += data[x] * multiplier[x] * binom(data.size() - x - 1, k - column - 1);
//counting the new multiplier factor
for(int helper = x + 1; helper < data.size(); helper++)
newmultiplier[helper]++;
}
//calculating new multiplier
for(int x = 0; x < data.size(); x++)
{
if(newmultiplier[x])
multiplier[x] *= newmultiplier[x];
}
}
return res;
}
int main() {
printvector(calculate({1,2,3}, 2)); //output 4 8
return 0;
}
std::next_permutation may help:
std::vector<int> sub_set(const std::vector<int>& a, int k)
{
std::vector<int> res(k, 0);
std::vector<bool> p(a.size() - k, false);
p.resize(a.size(), true);
do
{
int index = 0;
for (std::size_t i = 0; i != p.size(); ++i) {
if (p[i]) {
res[index++] += a[i];
}
}
} while (std::next_permutation(p.begin(), p.end()));
return res;
}
Live Demo
I have a square of side length 1 . Now, after each second, each square of side L will break into four squares each of side L/2.
I need the compute the total perimeter of the resulting figure, where total perimeter is defined as the sum of lengths of all line segments in the resulting figure. For example, the total perimeter of the image on the left is 4L while that on the right is 6L - 4L from the regular square edges and 2L from the internal line segments.
My code:
#include <cmath>
#include <cstdio>
#include <vector>
#include <iostream>
#include <algorithm>
using namespace std;
#define mod 1000000007
int main() {
int s;
cin>>s;
long long int ans=4;
for(int i=1;i<=s;i++)
ans+=1<<i;
ans=ans%mod;
cout<<ans<<endl;
return 0;
}
Since the final answer might not fit in a 64-bit signed integer, I am required to compute the answer modulo 1000000007.
For example, after 0 seconds, the length is 4.
After 1 second, the length is 6.
I am not getting the correct output. PLease help
Solve it recursively - let P(L, n) be the "perimeter" of the figure obtained after n iterations, starting with an LxL square. So, P(L, n+1) = 4*P(L/2,n) - 2*L. Also, since the perimeter is linear, P(L/2, n) = P(L, n)/2, giving you P(L,n) = 2*P(L,n-1) - 2*L. Substitute L=1 and run your loop.
int s;
cin>>s;
long long int ans=4;
for(int i=1;i<=s;i++)
{
ans = 2*(ans-1);
ans=ans%mod;
}
The perimeter after s seconds will be : 4+2(2^s-1)
So,
int main()
{
int s;
cout << "Enter Time: ";
cin >> s;
cout << "Perimeter = " << (4 + 2 * (pow( 2, s ) - 1));
}
You have an undivided square. When you split the square into 4 equal squares, you are essentially adding half of the initial perimeter. The outer walls of the original square are included as is in the new perimeter, and add to that the length of the 2 lines drawn inside it, the length of each of which is equal to the side of the square.
noOfsqaures = 1;
oldSide = 1; //one sqaure of side 1
oldPerimeter = 4*oldSide;
loop for the number of seconds
newPerimeter = oldPerimeter + 2*oldSide*noOfSquares
oldSide = oldSide/2; //for the next iteration
oldPermiter = newPermeter //for the next iteration
noOfSquares = noOfSquares*4;
o/p: 4(initial value) +
2 + 4 + 8 + 16 + 32 + ...
I think it would help you for coding. If you need I will give you code
for(int i=1;i<=s;i++)
{
ans+=1<<i;
}
I have a table which consists of nonnegative integers that are layed out in this manner: Each element in the table is the minimum value that does not appear to its left or above it. Here's an example of a 6x6 grid:
0 1 2 3 4 5
1 0 3 2 5 4
2 3 0 1 6 7
3 2 1 0 7 6
4 5 6 7 0 1
5 4 7 6 1 0
The first row and column begin with 0 1 2 3 4 5... In coordinates (x,x) is always a 0, as you can see. On each tile after that, you have to place the smallest positive number that doesn't already exist on the same row or column. Much like in a sudoku-puzzle: There cannot be a number twice on the same row and column.
Now I have to print the number in the given coordinates (y,x). For example [2, 5] = 5
I came up with a working solution, but it takes way too much memory and time, and I just know there's another way of doing this. My time limit is 1 second, and the coordinates I have to find the number at can go up to (1000000, 1000000).
Here's my code at the moment:
#include <iostream>
#include <vector>
int main()
{
int y, x, grid_size;
std::vector< std::vector<int> > grid;
std::cin >> y >> x; // input the coordinates we're looking for
grid.resize(y, std::vector<int>(x, 0)); // resize the vector and initialize every tile to 0
for(int i = 0; i < y; i++)
for(int j = 0; j < x; j++)
{
int num = 1;
if(i != j) { // to keep the zero-diagonal
for(int h = 0; h < y; h++)
for(int k = 0; k < x; k++) { // scan the current row and column
if(grid[h][j] == num || grid[i][k] == num) { // if we encounter the current num
num++; // on the same row or column, increment num
h = -1; // scan the same row and column again
break;
}
}
grid[i][j] = num; // assign the smallest number possible to the current tile
}
}
/*for(int i = 0; i < y; i++) { // print the grid
for(int j = 0; j < x; j++) // for debugging
std::cout << grid[i][j] << " "; // reasons
std::cout << std::endl;
}*/
std::cout << grid[y-1][x-1] << std::endl; // print the tile number at the requested coordinates
//system("pause");
return 0;
}
So what should I do? Is this easier than I think it is?
To summarize your question: You have a table where each element is the minimum nonnegative integer that does not appear to its left or above. You need to find the element at position (x,y).
The result is surprisingly simple: If x and y are 0-based, then the element at (x,y) is x XOR y. This matches the table you have posted. I have verified it experimentally for a 200x200 table.
The proof:
It's easy to see that the same number won't appear twice on the same row or column, because if x1^y = x2^y then necessarily x1=x2.
To see that x^y is minimal: Let a be a number smaller than x^y. Let i be the index (from the right) of the leftmost bit where a differs from x^y. The ith bit of a must be 0 and the ith bit of x^y must be 1.
Therefore, either x or y must have 0 in the ith bit. Suppose WLOG it was x that had 0. Represent x and y as:
x = A0B
y = C1D
Where A,B,C,D are sequences of bits, and B and D are i bits long. Since the leftmost bits of a are the same as those in x^y:
a^x = C0E
Where E is a sequence of i bits. So we can see that a^x < y. The value that appered in the (a^x)th row on the same column was: (a^x)^x = a. So the value a must have already appeared in the same row (or column, if it was y that had 0 in the ith bit). This is true for any value smaller than x^y, so x^y is indeed the minimum possible value.