Index

Dynamic Programming

Principle of Optimality and Recurrences

If a solution is optimal, any portion of it should be optimal
with respect to all the other possible choices of that particular portion. So, if a solution is not optimal, it shouldn't be further exploited.

Memoization Tables

Memoization tables are a way to store the information of a Dynamic Programming problem. They are used to speed up computing by saving the result of a certain operation, thus preventing running the same operation on the same input values more than once.

Shortest Path Using Dynamic Programming

cost(i,j)=min{c(j,k)+cost(i+1,k)}

Why it works? It makes sure that a partial solution is optimal. Using that principle, we can reuse partial optimal solutions to build a global solution.

0/1 Knapsack

val[i,j]=max(val[i1,j],val[i1,jwi]+vi)val[i,0]=0val[0,j]=0,j0val[i,j]=,i<0

Here, val[i1,j] means not including object i, and val[i1,jwi]+vi means including object i.
This gives a complexity of O(nW).

Longest Common Sub-Sequence (LCS)

Given 2 sequences X and Y, Z is a common sub-sequence if Z is a sub-sequence of X and Y.
Example:

c[i,j]={0if i=0 or j=0c[i1,j1]+1if i,j>0 and xi=yjmax(c[i1,j],c[i,j1])if i,j>0 and xiyj

By using this, we get a complexity of O(n×m)

Floyd-Warshall Algorithm for APSP

The goal is to find the shortest path between 2 nodes, passing through every edge.

Floyd-Warshall Algorithm:

wij={0if i=jweight of edge (i,j)if ij and (i,j)Eif ij and (i,j)E

In short, the diagonal is 0, if there is an edge from i to j use the weight of that edge, otherwise use .

Now, we need a matrix to use as a memoization table. In this case, we will use a 3D matrix of size n×n×n where dpij(k) means the shortest path from i to j routing through node 0,1,,k1,k.
In order to populate the matrix, use the following rules:

dpij(k)={wijif k=0min(dpij(k1),dpik(k1)+dpkj(k1))if k1

Lets break down the second case:

ijk
This gives a space complexity of O(V3), but it is possible to improve.
Since state k depends on state k1, it is possible to save one dimension, thus reducing the space complexity to O(V2).
In doing so, we can also simplify the rules to:

dpij={wijif k=0min(dpij,dpik+dpkj)if k0

Another matrix that is needed is a next matrix, an n×n 2D matrix to save the path. It is initialized iterating over w, and if there is a path between i and j then nextij should be j.

How to run the algorithm?

for (int k = 0; k < n; k++){
	for (int i = 0; i < n; i++){
		for (int j = 0; j < n; j++){
			if (dp[i][k] + dp[k][j] < dp[i][j]){
				dp[i][j] = dp[i][k] + dp[k][j];
				next[i][j] = next[i][k];
			}
		}
	}
}

If the graph has negative cycles, run the algorithm again, but if a better path is detected, mark the edges as and the next edge as 1.
This has a complexity of O(V3).

Exhaustive Search and Brand-and-Bound

There is not much to say about this.
Exhaustive search is searching every possible solution, and we can use bounding (pruning) to stop searching a certain branch if it is impossible to reach a solution.
Example:
Sum of subsets
Given an integer M and a set of positive integers E, find all subsets of E whose sum is equal to M.
Using backtracking, we can build a binary tree of either using or not using a certain element.
We can use a bounding function to stop searching if we have already exceeded M or if the sum of the remaining elements is smaller than M.
M = 5E = {1,2,4}0100213265371the sum of theremaining elements(4) is less thanthe target (5)the limit has beenexceeded (in thiscase there are nomore items, but ifthere were, wecould stopsearching thisbrancha solution hasbeen found, wecan stop searchingthis branch

NP and NP-Complete Algorithms

The Halting Problem

Let's imagine we have a machine (or program). Let's call this machine H. H takes a description of a program (p) and an input (i) for that program. Then, H says if problem p with input i is going to halt (finish) or not (run forever).
Now, let's extend H, calling it H. If H returns true, then H should run forever, and if H returns false, H should halt.
Let's run H, feeding itself as its arguments, so p is H and i is also H. This generates a contradiction:

Decision vs Optimization Problems

In decision problems, the answer should be yes/no, but in optimization problems, the answer should be a subset of feasible answers.
Abstract example:

P Problems (Polynomial Time)

P Problems are decision problems that can be solved in polynomial time (O(nk)).

NP Problems (Nondeterministic Polynomial Time)

A decision problem is a NP problem if it is possible to check if a solution is valid in polynomial time (O(nk)).

NP Hard Problems

A problem is NP-hard if an algorithm for it can be transformed into one for solving any NP problem. So, NP problems are at least as hard as any NP problem.

NP Complete Problems

If a problem has a known non-deterministic algorithm then we can classify it as NP-Complete.

Polynomial time reductions

Suppose that F and G are two problems. A polynomial time reduction, or just reduction from F to G is a way to show that F is no harder than G, which means that a polynomial time algorithm for G implies a polynomial time algorithm for F.

Satisfiability (SAT)

CNF Satisfiability serves as a base problem to relate all non-deterministic problems together, in a sense that if one of them is solved, then the others are also solved.
The CNF-SAT problem means taking a set and a propositional calculus formula and finding out which values make the formula true. It is a NP-Hard problem.
0100011100001111000011118 solutionsstate tree:
Now, we can relate the SAT with other problems, meaning that if we find a polynomial solution to SAT, then all the other problems can also be solved in polynomial time.
Can we relate the 0/1 Knapsack with the SAT?
At first glance, they might seem different, but in reality they are almost the same problem:
Let's imagine we have 3 items that we can use. So, the complexity is also 2n, since we can either use the item (1) or not use it (0). This generates a state tree very similar to the previous tree.
This means that SAT reduces 0/1 Knapsack:

0/1 KnapsackpSATorSAT0/1 Knapsack

Since SAT is also NP-Complete (because there is a know non-deterministic algorithm for it), 0/1 Knapsack also is NP-Complete.

Clique Problem

What is a clique?
A clique is a graph / subgraph where there is an edge connecting all pairs of vertices.
123412345
Knowing the maximum size of the clique or if there is a clique is a NP-Hard problem, but how do we prove it?
Abdul Bari explained it in a very simple way: https://www.youtube.com/watch?v=qZs767KQcvE&t=10s

Approximation Algorithms

I'm not going to prove the algorithms, the lecture slides have them.
The important concept is the approximation factor (ρ(n)):

max(CC,CC)ρ(n)where C is the solution produced by the approximationand Cis the optimal solution

So, a 2-approximation algorithm means that the solution is at most 2 times worse than the optimal solution.

Linear Programming

I highly recommend this video: https://www.youtube.com/watch?v=E72DWgKP_1Y. It explains the concept of linear programming in a very easy way.

Integer Linear Programming

A linear programming program is an integer linear programming if our values (x1, x2, ...) need to be integers.
We can start by solving it like a normal linear programming problem (ignoring the fact that the values need to be integers).
Then, the optimal solution will have values that are not integers (if that's not the case, then the solution found is the solution for the integer problem).
Now, we need to create different branches by either rounding one value up or down. Usually, we round the biggest value.
Example:
z = 27.67x1 = 2.33x2 = 2.67z = 27x1 = 3x2 = 2z = 26.75x1 = 1.75x2 = 3we could stopsearching this branch,because it's optimalsolution is worse thanthe optimal overallsolution, but let's keepexploringNo feasiblesolutionz = 25.57x1 = 1x2 = 3.42z = 24x1 = 0x2 = 4z = 23x1 = 1x2 = 3valid, yet notoptimal solutionsvalid andoptimal solution
A further explanation of the problem can be found here: https://www.youtube.com/watch?v=upcsrgqdeNQ&t=2s