How do I convert this recursion into iterative DP? - c++

I am trying to solve this problem :TRT.
Here is what I have done so far:
I designed a recursion for given problem and used memoization to get the solution accepted.
int recur(int l,int r,int level)
{
if(l==r)
return level*a[l];
if(dp[l][r])
return dp[l][r];
return dp[l][r]=max(level*a[l]+recur(l+1,r,level+1),level*a[r]+recur(l,r-1,level+1));
}
I am trying to solve this problem by bottom up dynamic programming but I can't think of the approach, this happens with most of the dynamic programming problems I am solving , I am able to design the recursion but fail at building the iterative dp. Can someone please help me with the approach to iterative dp solution once I have figured out the recursion ?
Edit: My bottom up DP solution based on Tempux's explanation:
int solve()
{
REP(i,n)
{
dp[i][i]=n*a[i];
}
REPP(i,1,n)
{
for(int j=0;j+i<n;j++)
{
dp[j][j+i]=max((n-i)*a[j]+dp[j+1][j+i],(n-i)*a[j+i]+dp[j][j+i-1]);
}
}
return dp[0][n-1];
}

Generally you just have to fill the values that are independent first (base cases). Then fill the values that are dependent on the values you have filled before.
In this case when l==r you have an independent value. So you just fill these first: [0][0] [1][1] [2][2] ... [n-1][n-1].
Now you can see that value of [l][r] is dependent on [l+1][r] and [l][r-1]. So now you can fill the values of [0][1] [1][2] [2][3] ... [n][n-1].
[0][1] is dependent on [0][0] and [1][1] which you have filled before
[1][2] is dependent on [1][1] and [2][2] which you have filled before
....
So now you recognize a pattern. You can fill the whole table if you proceed diagonally.
0 * * * * 0 1 * * * 0 1 2 * * 0 1 2 3 *
* 0 * * * * 0 1 * * * 0 1 2 * * 0 1 2 3
* * 0 * * * * 0 1 * * * 0 1 2 * * 0 1 2
* * * 0 * * * * 0 1 * * * 0 1 * * * 0 1
* * * * 0 * * * * 0 * * * * 0 * * * * 0
Here is one possible implementation:
for ( int d=0; d<=n-1; ++d ){
for ( int l=0; l<=n-1; ++l ){
int r = l+d;
if ( r >= n )
break;
int level = n-(r-l);
if ( l==r ){
dp[l][r] = level*v[l];
} else {
dp[l][r] = max( level*v[l] + dp[l+1][r],
level*v[r] + dp[l][r-1] );
}
}
}

Related

Building a segment tree in c++

I am trying to build a segment tree in c++. Following the recursive function for the same:
int buildTree(int node,int start,int end,int tree[])
{
// printf("Node is: %d\n",node);
printf("start: %d\tend:%d\tnode:%d\t\n",start,end,node);
if ( start == end )
{
// printf("start: %d,node: %d,array[start] : %d\n",start,node,array[start] );
tree[node] = array[start];
return array[start];
}
else
{
int mid = ( start + end ) / 2;
buildTree(2 * node ,mid + 1,end,tree);
buildTree(2 * node + 1,start,mid,tree);
tree[node] = tree[ 2 * node ] + tree[ 2 * node + 1 ];
return tree[node];
}
}
The array is globally defined:
int array[] = {1,2,3,4,5};
The tree after following call:
int main(int argc, char const *argv[])
{
int tree[100];
buildTree(0,0,4,tree);
for (int i = 0; i < 9; ++i)
{
printf("%d : %d\n",i, tree[i]);
}
return 0;
}
gives the output:
start: 0 end:4 node:0
start: 3 end:4 node:0
start: 4 end:4 node:0
start: 3 end:3 node:1
start: 0 end:2 node:1
start: 2 end:2 node:2
start: 0 end:1 node:3
start: 1 end:1 node:6
start: 0 end:0 node:7
0 : 15
1 : 6
2 : 3
3 : 3
4 : 474810352
5 : 32766
6 : 2
7 : 1
8 : 0
So, the nodes 4 and 5 are never processed. Where am I doing wrong? I think I am having hard time with recursion.
I build a segment tree using somehow the same implementation.
You should call the function buildTree with initial node = 1.
buildTree(1,0,4,tree);
This should fix the error.
Also most of the segment tree implementation codes use the node (2*node) for the range (start -> mid) and the node (2*node+1) for the range(mid+1 -> end).
I think it's a matter of convention. However sticking to the convention makes it easier for you to debug your code, and easier for other programmers to understand it.
So you can rewrite the recursive calls as:
buildTree(2 * node ,start,mid,tree);
buildTree(2 * node + 1,mid+1,end,tree);
Instead of:
buildTree(2 * node ,mid + 1,end,tree);
buildTree(2 * node + 1,start,mid,tree);

C++ equations, not sure if i wrote it correctly

Are and correctly written?
if(x>0.1){z = 2*n+x}
if else(x <= 0.1){x(pow,n) - 1 / sqrt(n(pow,2)) + x(pow,2) * n}
x = n / 2 * n(pow,2) + 3 * n - 2
x is correctly translated to C++.
As for the rest of the code, it would be:
if(x > 0.1) {
z = 2 * n + x;
}
else {
z = pow(x, n) - 1 / sqrt(pow(n, 2) + pow(x, 2) * n);
}

Loop diagonally through 2D array in one loop

How would one traverse an entire 2D array in one loop
e.g.
I want to push_back the diagonal elements into a buffer to process: 2 to 2, 3 to 3, 4 to 4
I have tried doing it in two separate loops but I can't process them together afterwards.
Example 2D array:
0 1 2 3 4 5 6
1 * * * * * *
2 * * * * * *
3 * * * * * *
4 * * * * * *
5 * * * * * *
6 * * * * * *
So, the buffer for (0,1) to (1,0) would be: one star from the grid
buffer for (0,2) to (2,0): two stars
buffer for (0,3) to (3,0): three stars
and so on...
note the buffer is a string.
If you want to get all the diagonal elements, the for loop would look something like this:
for(unsigned int i=0;i<yourArrayWidth;i++)
yourSum += yourArray[i][i];
if you want the numbers from top-left to bottom-right (so "\"), or:
for(unsigned int i=0;i<yourArrayWidth;i++)
yourSum += yourArray[yourArrayWidth-i][i];
if you want the numbers from top-right to bottom-left (so "/").
Where:
yourSum is some buffer you initialize before the traversing.
yourArrayWidth is the width of the array.
yourArray is the 2D array in your example, starting at [0][0].
For an array of M rows and N columns, you would have num=N+M-1 diagonals, which can each be obtained through:
int num = N+M-1;
int len = 1;
std::vector<std::string> res;
for (int i=0; i<num; ++i)
{
int startRow = std::min(i, M-1);
int startCol = i-startRow;
int len = std::min(startRow, N-1-startCol) + 1;
std::string str(len, '\0');
for (int j=0; j<len; ++j)
{
str[j] = arr[startRow-j][startCol+j];
}
res.push_back(str);
}
with i=0 being the "/" diagonal at the top-left, and i=N+M-1 being the diagonal at the bottom-right.

how can i change the b-spline curves from 4 point to 6?

I have a code on C++ it's b-spline curve that has 4 points if I want to change it to 6 point what shall I change in the code?
You can check the code:
#include "graphics.h"
#include <math.h>
int main(void) {
int gd, gm, page = 0;
gd = VGA;
gm = VGAMED;
initgraph(&gd, &gm, "");
point2d pontok[4] = { 100, 100, 150, 200, 170, 130, 240, 270 }; //pontok means points
int ap;
for (;;) {
setactivepage(page);
cleardevice();
for (int i = 0; i < 4; i++)
circle(integer(pontok[i].x), integer(pontok[i].y), 3);
double t = 0;
moveto((1.0 / 6) * (pontok[0].x * pow(1 - t, 3) +
pontok[1].x * (3 * t * t * t - 6 * t * t + 4) +
pontok[2].x * (-3 * t * t * t + 3 * t * t + 3 * t + 1) +
pontok[3].x * t * t * t),
(1.0 / 6) * (pontok[0].y * pow(1 - t, 3) +
pontok[1].y * (3 * t * t * t - 6 * t * t + 4) +
pontok[2].y * (-3 * t * t * t + 3 * t * t + 3 * t + 1) +
pontok[3].y * t * t * t));
for (t = 0; t <= 1; t += 0.01)
lineto(
(1.0 / 6) * (pontok[0].x * pow(1 - t, 3) +
pontok[1].x * (3 * t * t * t - 6 * t * t + 4) +
pontok[2].x * (-3 * t * t * t + 3 * t * t + 3 * t + 1) +
pontok[3].x * t * t * t),
(1.0 / 6) * (pontok[0].y * pow(1 - t, 3) +
pontok[1].y * (3 * t * t * t - 6 * t * t + 4) +
pontok[2].y * (-3 * t * t * t + 3 * t * t + 3 * t + 1) +
pontok[3].y * t * t * t));
/* Egerkezeles */ //Egerkezeles means mouse event handling
if (!balgomb)
ap = getactivepoint((point2d *)pontok, 4, 5);
if (ap >= 0 && balgomb) { //balgomb means left mouse button
pontok[ap].x = egerx; //eger means mouse
pontok[ap].y = egery;
}
/* Egerkezeles vege */
setvisualpage(page);
page = 1 - page;
if (kbhit())
break;
}
getch();
closegraph();
return 0;
}
From your formula, it looks like you are trying to draw a cubic Bezier curve. But the formula does not seem entirely correct. You can google "cubic Bezier curve" to find the correct formula. The Wikipedia page contains the formula for any degree of Bezier curve. You can find the "6-points" formula from there by using degree = 5.

Perspective and Bilinear transformations

I'm making a vector drawing application and noticed that Anti Grain Geometry have an example that does exactly what I want. http://www.antigrain.com/demo/index.html then below there is an example on perspective for Win32. I don't understand their cpp file. Based on this example. If I have a bunch of verticies to form an object, like their lion, and then I have 4 verticies as control points, how could I achieve their effect? Ex, what transformation do I apply to each point?
Thanks
From that very page you posted, there's a link to the source
code. I'll explain the bilinear transformation in
http://www.antigrain.com/__code/include/agg_trans_bilinear.h.html
The idea here is to find a transformation of the form:
output_x = a * input_x + b * input_x * input_y + c * input_y + d
output_y = e * input_x + f * input_x * input_y + g * input_y + h
The term "bilinear" comes from each of those equations being linear in
either of the input coordinates by themselves. We want to solve for
the right values of a, b, c, and d. Say you have the reference
rectangle r1, r2, r3, r4 which you want to map to (0,0), (1,0), (0,1),
(1,1) (or some image coordinate system).
For a,b,c,d:
0 = a * r1_x + b * r1_x * r1_y + c * r1_y + d
1 = a * r2_x + b * r2_x * r2_y + c * r2_y + d
0 = a * r3_x + b * r3_x * r3_y + c * r3_y + d
1 = a * r4_x + b * r4_x * r4_y + c * r4_y + d
For e,f,g,h:
0 = e * r1_x + f * r1_x * r1_y + g * r1_y + h
0 = e * r2_x + f * r2_x * r2_y + g * r2_y + h
1 = e * r3_x + f * r3_x * r3_y + g * r3_y + h
1 = e * r4_x + f * r4_x * r4_y + g * r4_y + h
You can solve this however you like best. (If you're familiar with
matrix notation, these are two matrix equations for which the matrix
is the same, and then you simply need to find the LU decomposition
once, and solve the two unknown vectors). The coefficients are then
applied to map the interior of the rectangle to the position in the
rectangle.
If by any chance you're looking for the inverse transform, that is,
if you want to know where a given pixel will land, you simply switch
inputs and outputs:
For a,b,c,d:
r1_x = a * 0 + b * 0 * 0 + c * 0 + d
r2_x = a * 1 + b * 1 * 0 + c * 0 + d
r3_x = a * 0 + b * 0 * 1 + c * 1 + d
r4_x = a * 1 + b * 1 * 1 + c * 1 + d
For e,f,g,h:
r1_y = e * 0 + f * 0 * 0 + g * 0 + h
r2_y = e * 1 + f * 1 * 0 + g * 0 + h
r3_y = e * 0 + f * 0 * 1 + g * 1 + h
r4_y = e * 0 + f * 0 * 1 + g * 1 + h
You're talking about perspective transformation from 2D planar onto a square 'in space' I think.
Well - This one is not that difficult. The mathematics are explained in the paper:
Heckbert, Paul, Fundamentals of
Texture Mapping and Image Warping,
Master’s thesis, UCB/CSD 89/516, CS
Division, U.C. Berkeley, June 1989.
(I don't link to the paper due to copyright reasons. It's available on the net and you shouldn't have any problems finding it though)
This gives you the math and some ready to use equations to do it.
If you are looking for some "easy to rip" code I suggest to download the OpenVG reference implementation and take a close look at the functions "vguComputeWarpQuadToSquare", "vguComputeWarpSquareToQuad" and "vguComputeWarpQuadToQuad" :-) They cover all you need.
Download here: http://www.khronos.org/registry/vg/ri/openvg-1.1-ri.zip
These functions will calculate a 3x3 matrix that does the transformation. To use this matrix you have to extend your 2D coordinates into 2D homogenous coordinates. That's not that difficult but beyond the scope of the question. If you need help to work with them I suggest that you ask that in a different question.