I am facing difficulty with Dynamic Programming. I was trying the trivial Coin Change problem- COIN CHANGE Problem UVa
I am trying to use top-down approach with memorization but I am getting TLE. Here is my code-
#include <bits/stdc++.h>
using namespace std;
#define ll long long
typedef vector <int > vi;
typedef vector <vi> vii;
const int maxn = 10000007;
int Set[maxn];
int Coin(int n,int m,vii & dp)
{
if(n==0)
return 1;
else if(n<0 || m<0)
return 0;
else if(dp[n][m]!=-1)
return dp[n][m];
else
{
dp[n][m]=Coin(n-Set[m],m,dp)+Coin(n,m-1,dp);
return dp[n][m];
}
}
int main()
{
int n,m=5;
Set[0]=50,Set[1]=25,Set[2]=10,Set[3]=5,Set[4]=1;
while(scanf("%d",&n)!=EOF)
{
vector <vector <int> > dp(n+1,vector<int> (m,-1));
dp[0][0]=0;
cout << Coin(n,m-1,dp) << endl;
}
}
I want to know am I doing memorization wrong or top-down will not work in this case and bottom-up approach is the only option.
You do have not to call Coin function for every testcase(each value of n) as m(number of types of coins) remains same in all cases so call it only once for maximum value which is 7489 here. and then answer for all testcase as dp[n][4]. Please see the code below for better understanding.
n = 7489;
vector <vector <int> > dp(n+1,vector<int> (m,-1));
dp[0][0]=0;
Coin(n,m-1,dp);
while(scanf("%d",&n)!=EOF)
{
cout<<dp[n][4]<<endl;
}
Related
I have a std::vector< std::vector< int> > that contains prime numbers. I wish to eliminate double entries, as the vector contents will be exported to a file and should only contain unique primes.
The prime numbers will come from certain intervals, fed to my algorithm through a file, e.g. (32,345). There may be cases where the intervals will overlap e.g. (54,434),(345,596). I wish to use std::unordered_set, since it will be the most efficient for my case.
I have seen examples with a std::vector< int> and tried to accommodate that to my needs, to no avail.
Here is code I tried, inspired by the print method of a 2d vector.
std::vector<std::vector<int> > sharedAnswersVec;
...
...
std::unordered_set<int> unique_primes;
for (auto i = 0; i < sharedAnswerVec.size(); i++)
{
for (auto j = 0; j < sharedAnswerVec[j].size(); j++)
{
unique_primes.insert({ i,j });
sharedAnswerVec.assign(unique_primes.begin(), unique_primes.end());
sort(sharedAnswerVec.begin(), sharedAnswerVec.end());
}
}
sharedAnswerVec cannot be std::vector< int>, has to be std::vector< std::vector< int> >.
With that in mind, what changes must I do in order to correct it?
I am a beginner trying to learn, so if the question seems silly to you, please bear that in mind.
You are trying to insert something into your std::unordered_set<int> something which is not an int.
It is not clear to me what your "intervals" are, or what you are doing when sorting. Perhaps this is some use?
#include <iostream>
#include <vector>
#include <set>
int main()
{
std::vector<std::vector<int> > sharedAnswersVec = {
{1,2,3,5,7,11,13,17,19,23,29},
{2,5,11,17,23,29}
};
std::set<int> unique_primes;
for ( const auto& v : sharedAnswersVec )
{
for ( auto i : v )
{
unique_primes.insert(i);
}
}
for ( auto i : unique_primes )
{
std::cout << i << std::endl;
}
return 0;
}
i am getting 0xc0000005 error(access violation error), where am i wrong in this code?
i couldnt debug this error. please help me.
question is this
Formally, given a wall of infinite height, initially unpainted. There occur N operations, and in ith operation, the wall is painted upto height Hi with color Ci. Suppose in jth operation (j>i) wall is painted upto height Hj with color Cj such that Hj >= Hi, the Cith color on the wall is hidden. At the end of N operations, you have to find the number of distinct colors(>=1) visible on the wall.
#include<iostream>
#include <bits/stdc++.h>
#include <algorithm>
using namespace std;
int main()
{
int t;
cin>>t;
for(int tt= 0;tt<t;tt++)
{
int h,c;
int temp = 0;
cin>>h>>c;
int A[h], B[c];
vector<int> fc;
for(int i = 0;i<h;i++)
{
cin>>A[i];
}
for(int j =0;j<h;j++)
{
cin>>B[j];
}
if(is_sorted(A,A+h))
{
return 1;
}
if(count(A,A+h,B[0]) == h)
{
return 1;
}
for(int i = 0;i<h;i++)
{
if(A[i]>=temp)
{
temp = A[i];
}
else
{
if(temp == fc[fc.size()-1])
{
fc[fc.size()-1] = B[i];
}
else
{
fc.push_back(B[i]);
}
}
}
}
}
There are several issues.
When reading values into B, your loop check is j<h. How many elements are in B?
You later look at fc[fc.size()-1]. This is Undefined Behavior if fc is empty, and is the likely source of your problem.
Other issues:
Don't use #include <bits/stdc++.h>
Avoid using namespace std;
Variable declarations like int A[h], where h is a variable, are not standard C++. Some compilers support them as an extension.
I am trying to solve this Problem on UVA.The question is about finding the max-flow in the graph.I used Edmond-karp algorithm but I am continuously getting wrong answer.Can any one tell me what's wrong in my code ?
My code :
#include<bits/stdc++.h>
using namespace std;
#define MX 1000000007
#define LL long long
#define ri(x) scanf("%d",&x)
#define rl(x) scanf("%lld",&x)
#define len(x) x.length()
#define FOR(i,a,n) for(int i=a;i<n;i++)
#define FORE(i,a,n) for(int i=a;i<=n;i++)
template<class T1> inline T1 maxi(T1 a,T1 b){return a>b?a:b;}
template<class T2> inline T2 mini(T2 a,T2 b){return a<b?a:b;}
int parent[101],G[101][101],rG[101][101];
bool bfs(int s,int t,int n)
{
bool vis[n+2];
memset(parent,0,sizeof parent);
memset(vis,0,sizeof vis);
queue<int>Q;
Q.push(s);
vis[s]=true;
while(!Q.empty())
{
int fnt=Q.front();
Q.pop();
for(int v=1;v<=n;v++)
{
if(!vis[v] and G[fnt][v]>0)
{
vis[v]=true;
parent[v]=fnt;
Q.push(v);
}
}
}
return vis[t];
}
int main()
{
int n,tst=1;
ri(n);
while(n)
{
int s,t,c,flow=0;
ri(s),ri(t),ri(c);
FORE(i,1,c)
{
int x,y,z;
ri(x),ri(y),ri(z);
G[x][y]+=z;
G[y][x]+=z;
}
while(bfs(s,t,n))
{
int path=9999999;
for(int v=t;v!=s;v=parent[v])
{
int u=parent[v];
path=mini(path,G[u][v]);
}
for(int v=t;v!=s;v=parent[v])
{
int u=parent[v];
G[u][v]-=path;
G[v][u]+=path;
}
flow+=path;
}
printf("Network %d\nThe bandwidth is %d.\n\n", tst++, flow);
ri(n);
}
}
You push flow the other way around:
G[u][v]-=path;
G[v][u]+=path;
This should be:
G[u][v] += path;
G[v][u] -= path;
Also, I'm not sure about this part:
if(!vis[v] and G[fnt][v]>0)
[...]
path=mini(path,G[u][v]);
Because you are also allowed to take paths on which the flow is negative. You should not change G, which seems to be your capacities graph. Instead, you should have a matrix F that stores how much flow you send. Then your two conditions should be changed to:
if (!vis[v] && G[fnt][v] != F[fnt][v])
[...]
path = mini(path, G[u][v] - F[u][v])
And push flow on F, not G.
You seem to have thought about this since you declared a matrix rG, but you're never using it.
There might be other issues too. It's hard to tell without knowing what problems you're seeing.
I had a question in my assignment to find whether a number was perfect square or not:
Perfect square is an element of algebraic structure which is equal to
the square of another element.
For example: 4, 9, 16 etc.
What my friends did is, if n is the number, they looped n - 1 times calculating n * n:
// just a general gist
int is_square = 0;
for (int i = 2; i < n; i++)
{
if ((i * i) == n)
{
std::cout << "Yes , it is";
is_square = 1;
break;
}
}
if (is_square == 0)
{
std::cout << "No, it is not";
}
I came up with a solution as shown below:
if (ceil(sqrt(n)) == floor(sqrt(n)))
{
std::cout << "Yes , it is";
}
else
{
std::cout << "no , it is not";
}
And it works properly.
Can it be called as more optimized solution than others?
The tried and true remains:
double sqrt(double x); // from lib
bool is_sqr(long n) {
long root = sqrt(n);
return root * root == n;
}
You would need to know the complexity of the sqrt(x) function on your computer to compare it against other methods. By the way, you are calling sqrt(n) twice ; consider storing it into a variable (even if the compiler probably does this for you).
If using something like Newton's method, the complexity of sqrt(x) is in O(M(d)) where M(d) measures the time required to multiply two d-digits numbers. Wikipedia
Your friend's method does (n - 2) multiplications (worst case scenario), thus its complexity is like O(n * M(x)) where x is a growing number.
Your version only uses sqrt() (ceil and floor can be ignored because of their constant complexity), which makes it O(M(n)).
O(M(n)) < O(n * M(x)) - Your version is more optimized than your friend's, but is not the most efficient. Have a look at interjay's link for a better approach.
#include <iostream>
using namespace std;
void isPerfect(int n){
int ctr=0,i=1;
while(n>0){
n-=i;
i+=2;
ctr++;
}
if(!n)cout<<"\nSquare root = "<<ctr;
else cout<<"\nNot a perfect square";
}
int main() {
isPerfect(3);
isPerfect(2025);
return 0;
}
I don't know what limitations do you have but perfect square number definition is clear
Another way of saying that a (non-negative) number is a square number,
is that its square roots are again integers
in wikipedia
IF SQRT(n) == FLOOR(SQRT(n)) THEN
WRITE "Yes it is"
ELSE
WRITE "No it isn't"
examples sqrt(9) == floor(sqrt(9)), sqrt(10) == floor(sqrt(10))
I'll recommend this one
if(((unsigned long long)sqrt(Number))%1==0) // sqrt() from math library
{
//Code goes Here
}
It works because.... all Integers( & only positive integers ) are positive multiples of 1
and Hence the solution.....
You can also run a benchmark Test like;
I did with following code in MSVC 2012
#include <iostream>
#include <conio.h>
#include <time.h>
#include <math.h>
using namespace std;
void IsPerfect(unsigned long long Number);
void main()
{
clock_t Initial,Final;
unsigned long long Counter=0;
unsigned long long Start=Counter;
Start--;
cout<<Start<<endl;
Initial=clock();
for( Counter=0 ; Counter<=100000000 ; Counter++ )
{
IsPerfect( Counter );
}
Final=clock();
float Time((float)Final-(float)Initial);
cout<<"Calculations Done in "<< Time ;
getch();
}
void IsPerfect( unsigned long long Number)
{
if(ceil(sqrt(Number)) == floor(sqrt(Number)))
//if(((unsigned long long)sqrt(Number))%1==0) // sqrt() from math library
{
}
}
Your code took 13590 time units
Mine just 10049 time units
Moreover I'm using few extra steps that is Type conversion
like
(unsigned long long)sqrt(Number))
Without this it can do still better
I hope it helps .....
Have a nice day....
Your solutions is more optimized, but it may not work. Since sqrt(x) may return the true square root +/- epsilon, 3 different roots must be tested:
bool isPerfect(long x){
double k = round( sqrt(x) );
return (n==(k-1)*(k-1)) || (n==k*k) || (n==(k+1)*(k+1));
}
This is simple python code for finding perfect square r not:
import math
n=(int)(input())
giv=(str)(math.sqrt(n))
if(len(giv.split('.')[1])==1):
print ("yes")
else:
print ("No")
Halo I just write code to perform Matrix chain multiplication, which can be solved by Dynamic Programming
http://en.wikipedia.org/wiki/Matrix_chain_multiplication#A_Dynamic_Programming_Algorithm
Here is the code I wrote, which I think is simpler than the one provided by wikipedia. So I doubt am i doing dynamic programming or not?
and I can't figure out the time complexity of my program. Can someone help me to figure the time complexity of this program?
Here's my guess..
the for loop will run n times for each call? if mem is not used..
for each loop, it will then expand into two
if mem is used, it prevent recalculation...
ahhh I can't figure it out, hope someone can help me :-)
#include <iostream>
#include <cstdlib>
#include <cstring>
#include <climits>
using namespace std;
int mem[10][10];
int row[10];
int col[10];
int m[10];
#define NUM 4
int DP(int c, int r){
if(mem[c][r] != INT_MAX) return mem[c][r];
if(c == r) return 0;
int min_cost;
for(int j=c; j<r; j++){
min_cost = DP(c, j) + DP(j+1, r) + m[c-1]*m[j]*m[r];
if(min_cost < mem[c][r])
mem[c][r] = min_cost;
}
return mem[c][r];
}
int main(){
for(int i=0; i< 10;i++){
for(int j=0; j<10;j++){
mem[i][j] = INT_MAX;
}
}
int n = NUM; // MAX 4 matrix
int a,b;
for(int i=0; i< NUM+1; i++){
cin >> a;
m[i] = a;
}
cout << "Lowest Cost for matrix multiplicatoin " << DP(1,NUM);
}
The technique you have used is called memoization. Most of the time, you may solve DP problems using memoization with little (or no) overhead.
The complexity of your implementation is just like the original DP solution: O(n^3) (Note: Every cell of mem array should be computed at least once, and each cell takes O(n) time to be computed. Further computation of a cell, does not involve any loop, since it would be a simple lookup.)
See also http://en.wikipedia.org/wiki/Memoization