Am I using Dynamic Programming? Matrix chain multiplication in c - algorithm

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

Related

Why doesn't move-assigning a std::vector seem to have any performance benefit over copying in this code?

Since move-assigning a std::vector is is a O(1) time operation and copying a std::vector to another is O(N) (where N is the sum of the sizes of the 2 vectors), I expected to see move-assignment having a significant performance advantage over copying. To test this, I wrote the following code, which move-assigns/copies a std::vector nums2 of size 1000 to nums 100,000 times.
#include <iostream>
#include <vector>
#include <chrono>
using namespace std;
int main()
{
auto start = clock();
vector <int> nums;
for(int i = 0; i < 100000; ++i) {
vector <int> nums2(1000);
for(int i = 0; i < 1000; ++i) {
nums2[i] = rand();
}
nums = nums2; // or nums = move(nums2);
cout << (nums[0] ? 1:0) << "\b \b"; // prevent compiler from optimizing out nums (I think)
}
cout << "Time: " << (clock() - start) / (CLOCKS_PER_SEC / 1000) << '\n';
return 0;
}
The compiler I am using is g++ 7.5.0. When running with g++ -std=c++1z -O3, both the move-assign/copy versions take around 1600ms, which does not match with the hypothesis that move-assignment has any significant performance benefit. I then tested using std::swap(nums, nums2) (as an alternative to move-assignment), but that also took around the same time.
So, my question is, why doesn't move-assigning a std::vector to another seem to have a performance advantage over copy-assignment? Do I have a fundamental mistake in my understanding of C++ move-assignment?

How to find the maximum gcd for a set and an integer efficiently?

Given a set of integer S, and some questions containing an integer w.
For each question, compute max{gcd(w,x)} (x in S).
The range for all the numbers, n, is also given, so w<n,x<n (x in S).
I have tried simply computing all the gcds, but it is not efficient enough. I think the key is doing some pretreatment so that each question can be done in O(log n) or less.
Well, this is what I tried:
#include "iostream"
using namespace std;
int gcd(int a,int b){
return b?gcd(b,a%b):a;
}
int n,m,S[1000010],w;
int main(){
cin>>n;
for(int i=0;i<n;i++){
cin>>S[i];
}
cin>>m;
for(int i=0;i<m;i++){
cin>>w;
int mx=0;
for(int j=0;j<n;j++){
mx=max(mx,gcd(w,S[j]));
}
cout<<mx<<endl;
}
return 0;
}
An opportunity for optimization is to reduce the subset of S to be considered. Since gcd(w,x) cannot be greater than x, elements less than the current maximum can be skipped.
Given a set of integer, I use set <int> S;:
for (auto it = S.rbegin(); it != S.rend(); ++it)
if (*it <= mx)
break;
else
mx = max(mx, gcd(w, *it));

Hackerearth bubbleSort

In Hackerearth i tried solving bubble sort swap counting. and my output always different from correct output.for example;
my output is 2475 and correct output is 2788
#include <iostream>
using namespace std;
int main()
{
int *A,tm,times=0;
cin >> tm;
A = new int[tm];
for(int i = 0; i<tm;i++) {cin >> A[i];}
int temp;
for(int i = 0; i<tm;i++){
for(int j = 0; j < tm-i-1;j++){
if(A[j] > A[j+1]){
times++;;
temp = A[j];
A[j] = A[j+1];
A[j] = temp;
}
}
}
cout << times;
return 0;
}
Am i doing something wrong or correct outputs are wrong?
In the swap logic, in place of
A[j]=temp;
write
A[j+1]=temp;
In the outer for loop, i<tm-1 instead of i<tm
May be this is irrelevant, but it is possible to find the number of inversion with a better complexity. This solution will require O(n^2). It can be done in O(nlogn) time complexity. The idea is to use merge sort and at merging state you already know how many values are greater/smaller from a value without actually counting them. While merging, if a value of right subarray is greater, then all other values right of it are also greater. You just need to count how many values are at right. A detailed and pleasant explanation is provided here.
Number of swaps performed by Bubble-Sort on a given array
http://www.geeksforgeeks.org/counting-inversions/

What is wrong with my selection sort?

My implementation of selection sort does not work in case of j < n-2 or n-1 or n. What am I doing wrong?
Is there an online IDE that lets us put a watch for the control loops?
#include <stdio.h>
#define n 4
int main(void) {
int a[n]={4,3,2,1};
int j,min;
for(int i=0;i<n;i++){
min=i;
for(j=i+1;j<n-3;j++)
if(a[j]>a[j+1])
min=j+1;
if(min!=i){
int t=a[min];
a[min]=a[i];
a[i]=a[t];
}
}
for(int i=0;i<n;i++)
printf("%d",a[i]);
return 0;
}
I tried it here
Your code has indeed a strange limit on n-3, but it has also some other flaws:
To find a minimum you should compare with the current minimum (a[min]), not the next/previous element in the array
The code to swap is not correct: the last assignment should not be from a[t], but t itself.
Here is the corrected code:
int main(void) {
int a[n]={4,3,2,1};
int j,min;
for(int i=0;i<n;i++){
min=i;
for(j=i+1;j<n;j++)
if(a[min]>a[j])
min=j;
if(min!=i){
int t=a[min];
a[min]=a[i];
a[i]=t;
}
}
for(int i=0;i<n;i++)
printf("%d",a[i]);
return 0;
}
https://ideone.com/AGJDPS
NB: To see intermediate results in an online IDE, why not add printf calls inside the loop? Of course, for larger code projects you'd better use a locally installed IDE with all the debugging features, and step through the code.

Finding an efficient algorithm

You are developing a smartphone app. You have a list of potential
customers for your app. Each customer has a budget and will buy the app at
your declared price if and only if the price is less than or equal to the
customer's budget.
You want to fix a price so that the revenue you earn from the app is
maximized. Find this maximum possible revenue.
For instance, suppose you have 4 potential customers and their budgets are
30, 20, 53 and 14. In this case, the maximum revenue you can get is 60.
**Input format**
Line 1 : N, the total number of potential customers.
Lines 2 to N+1: Each line has the budget of a potential customer.
**Output format**
The output consists of a single integer, the maximum possible revenue you
can earn from selling your app.
Also, upper bound on N is 5*(10^5) and upper bound on each customer's budget is 10^8.
This is a problem I'm trying to solve . My strategy was to sort the list of budgets and then multiply each of those with its position-index in the sequence - and then print the max of the resulting sequence. However this seems to be quite time-inefficient (at least in the way I'm implementing it - I've attached the code for reference). My upper bound on time is 2 seconds. Can anyone help me find a
more time-efficient algorithm (or possibly a more efficient way to implement my algorithm) ?
Here is my solution :
#include <iostream>
#include <stdlib.h>
#include <stdio.h>
#include <math.h>
using namespace std;
long long max(long long[],long long);
void quickSortIterative(long long[],long long,long long);
long long partition(long long[],long long,long long);
void swap(long long*,long long*);
int main(){
long long n,k=1;
scanf("%lld",&n);
if(n<1 || n > 5*((long long)pow(10,5))){
exit(0);
}
long long budget[n],aux[n];
for(long long i=0;i<n;i++){
scanf("%lld",&budget[i]);
if(budget[i]<1 || budget[i] > (long long)pow(10,8)){
exit(0);
}
}
quickSortIterative(budget,0,n-1);
for(long long j=n-1;j>=0;j--){
aux[j] = budget[j]*k;
k++;
}
cout<<max(aux,n);
return 0;
}
long long partition (long long arr[], long long l, long long h){
long long x = arr[h];
long long i = (l - 1);
for (long long j = l; j <= h- 1; j++)
{
if (arr[j] <= x)
{
i++;
swap (&arr[i], &arr[j]);
}
}
swap (&arr[i + 1], &arr[h]);
return (i + 1);
}
void swap ( long long* a, long long* b ){
long long t = *a;
*a = *b;
*b = t;
}
void quickSortIterative(long long arr[], long long l, long long h){
long long stack[ h - l + 1 ];
long long top = -1;
stack[ ++top ] = l;
stack[ ++top ] = h;
while ( top >= 0 ){
h = stack[ top-- ];
l = stack[ top-- ];
long long p = partition( arr, l, h );
if ( p-1 > l ){
stack[ ++top ] = l;
stack[ ++top ] = p - 1;
}
if ( p+1 < h ){
stack[ ++top ] = p + 1;
stack[ ++top ] = h;
}
}
}
long long max(long long arr[],long long length){
long long max = arr[0];
for(long long i=1;i<length;i++){
if(arr[i]>max){
max=arr[i];
}
}
return max;
}
Quicksort can take O(n^2) time for certain sequences (often already sorted sequences are bad).
I would recommend you try using a sorting approach with guaranteed O(nlogn) performance (e.g. heapsort or mergesort). Alternatively, you may well find that using the sort routines in the standard library will give better performance than your version.
You might use qsort in C or std::sort in C++, which is most likely faster than your own code.
Also, your "stack" array will cause you trouble if the difference h - l is large.
I have used STL library function sort() of C++. It's time complexity is O(nlogn). Here, you just need to sort the given array and check from maximum value to minimum value for given solution. It is O(n) after sorting.
My code which cleared all the test cases :
#include <algorithm>
#include <stdio.h>
#include <cmath>
#include <iostream>
using namespace std;
int main(){
long long n, a[1000000], max;
int i, j;
cin>>n;
for(i = 0; i < n; i++){
cin>>a[i];
}
sort(a, a + n);
max = a[n - 1];
for(i = n - 2; i >= 0; i--){
//printf("%lld ", a[i]);
if(max < (a[i] * (n - i)))
max = a[i] * (n - i);
}
cout<<max<<endl;
return 0;
}
I dont know if my answer is right or wrong please point out mistakes if there is any
#include<stdio.h>
void main()
{
register int i,j;
long long int n,revenue;
scanf("%Ld",&n);
long long int a[n];
for(i=0;i<n;i++)
scanf("%Ld",&a[i]);
for (i=0;i<n;i++)
{
for(j=i+1;j<n;j++)
{
if(a[i]>a[j])
{
a[i]=a[i]+a[j];
a[j]=a[i]-a[j];
a[i]=a[i]-a[j];
}
}
}
for(i=0;i<n;i++)
a[i]=(n-i)*a[i];
revenue=0;
for(i=0;i<n;i++)
{
if(revenue<a[i])
revenue=a[i];
}
printf("%Ld\n",revenue);
}
passed all the test cases
n=int(input())
r=[]
for _ in range(n):
m=int(input())
r.append(m)
m=[]
r.sort()
l=len(r)
for i in range(l):
m.append((l-i)*r[i])
print(max(m))
#include <iostream>
#include <bits/stdc++.h>
using namespace std;
int main() {
// your code goes here
long long n;
std::cin >> n;
long long a[n];
for(long long i=0;i<n;i++)
{
std::cin >> a[i];
}
sort(a,a+n);
long long max=LONG_MIN,count;
for(long long i=0;i<n;i++)
{
if(a[i]*(n-i)>max)
{
max=a[i]*(n-i);
}
}
std::cout << max << std::endl;
return 0;
}
The following solution is in C programming Language.
The Approach is:
Input the number of customers.
Input the budgets of customers.
Sort the budget.
Assign revenue=0
Iterate through the budget and Multiply the particular budget with the remaining budget values.
If the previous-revenue < new-revenue. assign the new-revenue to revenue variable.
The code is as follows:
#include <stdio.h>
int main(void) {
int i,j,noOfCustomer;
scanf("%d",&noOfCustomer);
long long int budgetOfCustomer[noOfCustomer],maximumRevenue=0;
for(i=0;i<noOfCustomer;i++)
{
scanf("%Ld",&budgetOfCustomer[i]);
}
for(i=0;i<noOfCustomer;i++)
{
for(j=i+1;j<noOfCustomer;j++)
{
if(budgetOfCustomer[i]>budgetOfCustomer[j])
{
budgetOfCustomer[i]=budgetOfCustomer[i] + budgetOfCustomer[j];
budgetOfCustomer[j]=budgetOfCustomer[i] - budgetOfCustomer[j];
budgetOfCustomer[i]=budgetOfCustomer[i] - budgetOfCustomer[j];
}
}
}
for(i=0;i<noOfCustomer;i++)
{
budgetOfCustomer[i]=budgetOfCustomer[i]*(noOfCustomer-i);
}
for(i=0;i<noOfCustomer;i++)
{
if(maximumRevenue<budgetOfCustomer[i])
maximumRevenue=budgetOfCustomer[i];
}
printf("%Ld\n",maximumRevenue);
return 0;
}

Resources