Uploaded by cegix71657

Динамичко програмирање: Алгоритми и примери

advertisement
Dynamic Programming
Change Making
Get the least amount of coins to make a change.
Consider an array of coins and an array stores the solution for each subproblem called
solution
Equation
Complexity
Consider the amount to make change for and total of coins provided,
Time:
Space:
Example
coins = [1, 2, 5]
amount = 11
At first table starts with: amount + 1 for each cell
H1
0
1
2
3
4
5
6
7
8
9
10
11
12
12
12
12
12
12
12
12
12
12
12
12
0
1
2
3
4
5
6
7
8
9
10
11
0
1
1
2
2
1
2
2
3
3
2
3
Code
#include <iostream>
using namespace std;
int changeMaking(int coins[], int size, int amount){
int solution[amount + 1];
std::fill_n(solution, amount + 1, amount + 1);
solution[0] = 0;
for (int i = 1; i <= amount; i++)
{
for (int j = 0; j < size; j++)
{
if (coins[j] <= i)
solution[i] = min(solution[i], solution[i - coins[j]] + 1);
}
}
return solution[amount] > amount ? -1: solution[amount];
}
int main()
{
int size = 3;
int coins[size] = {1, 2, 5};
int amount = 11;
cout << changeMaking(coins, size, amount);
return 0;
}
Longest Common Subsequence
Longest Common Subsequence (2 Strings) - Dynamic Programming & Competing
Subproblems - YouTube
Equation
Consider an array A that stores the solution for each common subsequence of each
subproblem.
Thus, Three cases could occur:
1.
if i = 0 or j = 0 which means two empty strings.
2.
, if both characters from both strings are matched
3.
, otherwise
Complexity
Consider two strings s1 and s2 with the respective lengths n and m
Time:
Space:
Example
Code
public int LCS(String s1, String s2) {
int cache[][] = new int[s2.length() + 1][s1.length() + 1];
for (int s2Row = 0; s2Row <= s2.length(); s2Row++)
{
for (int s1Col = 0; s1Col <= s1.length(); s1Col++)
{
if (s2Row == 0 || s1Col == 0)
cache[s2Row][s1Col] = 0;
else if (s2.charAt(s2Row - 1) == s1.charAt(s1Col - 1))
cache[s2Row][s1Col] = cache[s2Row - 1][s1Col - 1] + 1;
else
{
cache[s2Row][s1Col] = Math.max(
cache[s2Row - 1][s1Col], cache[s2Row][s1Col - 1]
);
}
}
}
return cache[s2.length()][s1.length()];
}
Coin Collection
A robot collecting coins in a grid of M x N . What's the maximum number of coins can be
collected? The robot can only go forward to the right or down.
Equation
Consider an array board is the grid of coins and solution that stores the maximum number
of coins collected at specific (i, j) .
Complexity
Filling the table takes:
Tracing back:
Example
Code
#include <iostream>
using namespace std;
int main()
{
const int rows = 6;
const int columns = 6;
int board[rows][columns] =
{
{0, 0, 1, 0, 0, 1},
{0, 0, 0, 1, 0, 0},
{0, 1, 0, 0, 1, 0},
{0, 0, 0, 1, 0, 0},
{1, 0, 0, 0, 1, 0},
{0, 0, 1, 0, 0, 1},
};
int solution[rows + 1][columns + 1];
for(int i = 0; i <= rows; i++)
solution[i][0] = 0;
for(int j = 0; j <= columns; j++)
solution[0][j] = 0;
for(int i = 1; i <= rows; i++)
{
for(int j = 1; j <= columns; j++){
solution[i][j] =
max(solution[i - 1][j], solution[i][j - 1]) + board[i-1][j-1];
}
}
int i = rows, j = columns;
stack<coordinate> coordinates;
// trace back
while(i > 0 && j > 0){
if(solution[i][j] == solution[i][j - 1] + board[i - 1][j - 1]){
coordinates.push({i, j - 1});
}
else if(solution[i][j] == solution[i-1][j] + board[i - 1][j - 1]){
coordinates.push({i - 1, j});
}
i--;
j--;
}
for(int i = 0; i <= rows; i++)
{
for(int j = 0; j <= columns; j++)
{
cout << solution[i][j] << " ";
}
cout << endl;
}
return 0;
}
Dynamic Programming 0/1 Knapsack
Consider a knapsack of capacity = 7
Value
Weight
#1
1
1
#2
4
3
#3
5
4
#4
7
5
0
1
2
3
4
5
6
7
1
0
1
1
1
1
1
1
1
3
0
1
1
4
5
5
5
5
4
0
1
1
4
5
6
6
9
5
0
1
1
4
5
7
8
9
Coin-row
Example: 5, 1, 2, 10, 6, 3
index
0
coins
V(n)
0
1
2
3
4
5
6
5
1
2
10
6
3
5
5
7
15
15
18
where
is the number of coins.
Equation
Complexity
Filling the table requires:
Tracing back takes linear time.
Code
#include <iostream>
#include <vector>
using namespace std;
vector<int> maximumAmountOfCoins(vector<int> coins, int size)
{
if(size < 2) return coins;
int solution[size + 1];
solution[0] = 0;
solution[1] = coins[0];
for(int i = 2; i <= size + 1; i++)
solution[i] = max(coins[i - 1] + solution[i - 2], solution[i 1]);
int maximumCoins = solution[size];
vector<int> chosen;
for(int i = size; i >= 0; i--)
{
if(maximumCoins > solution[i - 1])
{
maximumCoins -= coins[i - 1];
chosen.push_back(coins[i-1]);
}
}
chosen.push_back(solution[size]);
return chosen;
}
int main()
{
vector<int> coins = {5, 1, 2, 10, 6, 2};
vector<int> chosenCoins = maximumAmountOfCoins(coins, coins.size());
cout << "Chosen Coins: ";
for(auto iterator = chosenCoins.begin(); iterator !=
chosenCoins.end(); ++iterator)
{
if(std::next(iterator) == chosenCoins.end())
{
cout << "\nMaximum Coins: " << *iterator << endl;
break;
}
cout << *iterator << " ";
}
return 0;
}
Binomial Coefficient
Download