如何通过memoization将这段回溯代码变成动态编程代码呢?
How to change this backtracking code into a dynamic programming code by using memoization?
我正在尝试学习动态规划,因此我正在尝试解决 UVA 11450。因为我知道我可以使用回溯来解决这个问题,所以我决定使用回溯来解决它,然后在代码中添加记忆。但是,我无法做到这一点。
这是没有记忆的注释代码:
#include <bits/stdc++.h>
using namespace std;
bool b; // this tells us if a solution is found or not
int c; // store input c
vector <vector <int>> arr; // declare a global array to store the type and cost of the garments
int money = INT_MAX; // these two fields store the most optimal solution found so far
vector <int> garr;
// this function fills 'c' - the candidates for the k'th postition
void construct_candidates(vector <int> &a, int k, int m, vector<int> &c)
{
for (int i: arr[k])
{
if (i <= m ) c.push_back(i); // if cost of the model 'i' of garment 'k' is less than or equal to money remaining,
} // put it in array 'c'.
}
void backtrack(vector <int> &a, int k, int m)
{
vector <int> c; // this array stores the candidates for postion k.
if (k == a.size() - 1) // if (is_a_soln) process_solution
{
if (m < money)
{
b = true;
money = m;
garr = a;
}
}
else // else backtrack with updated parameters
{
k++;
construct_candidates(a, k , m, c);
for (int i = 0; i < c.size(); i++)
{
a[k] = c[i];
backtrack(a, k, m - c[i]);
}
}
}
int main()
{
int n;
cin >> n;
while (n--)
{
b = false; // initialising global variables
money = INT_MAX;
arr.clear();
int m;
cin >> m >> c;
arr = vector <vector <int>>(c);
for(int i = 0; i < c; i++) // storing the input in arr
{
int k;
cin >> k;
arr[i] = vector <int> (k);
for (int j = 0; j < k; j++)
{
cin >> arr[i][j];
}
}
vector <int> a(c, -1); // the backtracking code will attempt
//to fill this array with optimal garments
backtrack(a, -1, m);
if (b) cout <<m - money << endl;
else cout << "no solution" << endl;
}
return 0;
}
现在,为了添加记忆,我尝试这样做:
vector <vector <int>> dp(20, vector<int> (201, -1));
void backtrack(vector <int> &a, int k, int m)
{
if (dp[k][m] != -1) // this is
{ // the
k++; // part
a[k] = dp[k][m]; // that
backtrack(a, k, m - a[k]); // is
} // added
else
{
vector <int> c;
if (k == a.size() - 1)
{
if (m < money)
{
b = true;
money = m;
garr = a;
}
}
else
{
k++;
construct_candidates(a, k , m, c);
for (int i = 0; i < c.size(); i++)
{
a[k] = c[i];
backtrack(a, k, m - c[i]);
}
}
}
}
但我不知道在哪里或如何添加实际将最佳服装放在 DP 中位置 k 的部分 table。非常感谢任何帮助。
感谢@AlexanderZhang 非常有帮助的评论,我已经解决了这个问题。如果有兴趣,请参阅他的评论以获取详细信息。这是代码:
vector <vector <int>> dp(20, vector<int> (201, -1));
void backtrack(vector <int> &a, int k, int m)
{
k++;
if (dp[k][m] != -1)
{
return;
}
else
{
dp[k][m]++;
vector <int> c; // this array stores the candidates for postion k.
// for (int kj : a) cout << kj << " ";
// cout << endl;
if (k == a.size() ) // if (is_a_soln) process_solution
{
if (m < money)
{
b = true;
money = m;
garr = a;
}
}
else // else backtrack with updated parameters
{
// k++;
construct_candidates(a, k , m, c);
for (int i = 0; i < c.size(); i++)
{
a[k] = c[i];
backtrack(a, k, m - c[i]);
}
}
}
}
我正在尝试学习动态规划,因此我正在尝试解决 UVA 11450。因为我知道我可以使用回溯来解决这个问题,所以我决定使用回溯来解决它,然后在代码中添加记忆。但是,我无法做到这一点。
这是没有记忆的注释代码:
#include <bits/stdc++.h>
using namespace std;
bool b; // this tells us if a solution is found or not
int c; // store input c
vector <vector <int>> arr; // declare a global array to store the type and cost of the garments
int money = INT_MAX; // these two fields store the most optimal solution found so far
vector <int> garr;
// this function fills 'c' - the candidates for the k'th postition
void construct_candidates(vector <int> &a, int k, int m, vector<int> &c)
{
for (int i: arr[k])
{
if (i <= m ) c.push_back(i); // if cost of the model 'i' of garment 'k' is less than or equal to money remaining,
} // put it in array 'c'.
}
void backtrack(vector <int> &a, int k, int m)
{
vector <int> c; // this array stores the candidates for postion k.
if (k == a.size() - 1) // if (is_a_soln) process_solution
{
if (m < money)
{
b = true;
money = m;
garr = a;
}
}
else // else backtrack with updated parameters
{
k++;
construct_candidates(a, k , m, c);
for (int i = 0; i < c.size(); i++)
{
a[k] = c[i];
backtrack(a, k, m - c[i]);
}
}
}
int main()
{
int n;
cin >> n;
while (n--)
{
b = false; // initialising global variables
money = INT_MAX;
arr.clear();
int m;
cin >> m >> c;
arr = vector <vector <int>>(c);
for(int i = 0; i < c; i++) // storing the input in arr
{
int k;
cin >> k;
arr[i] = vector <int> (k);
for (int j = 0; j < k; j++)
{
cin >> arr[i][j];
}
}
vector <int> a(c, -1); // the backtracking code will attempt
//to fill this array with optimal garments
backtrack(a, -1, m);
if (b) cout <<m - money << endl;
else cout << "no solution" << endl;
}
return 0;
}
现在,为了添加记忆,我尝试这样做:
vector <vector <int>> dp(20, vector<int> (201, -1));
void backtrack(vector <int> &a, int k, int m)
{
if (dp[k][m] != -1) // this is
{ // the
k++; // part
a[k] = dp[k][m]; // that
backtrack(a, k, m - a[k]); // is
} // added
else
{
vector <int> c;
if (k == a.size() - 1)
{
if (m < money)
{
b = true;
money = m;
garr = a;
}
}
else
{
k++;
construct_candidates(a, k , m, c);
for (int i = 0; i < c.size(); i++)
{
a[k] = c[i];
backtrack(a, k, m - c[i]);
}
}
}
}
但我不知道在哪里或如何添加实际将最佳服装放在 DP 中位置 k 的部分 table。非常感谢任何帮助。
感谢@AlexanderZhang 非常有帮助的评论,我已经解决了这个问题。如果有兴趣,请参阅他的评论以获取详细信息。这是代码:
vector <vector <int>> dp(20, vector<int> (201, -1));
void backtrack(vector <int> &a, int k, int m)
{
k++;
if (dp[k][m] != -1)
{
return;
}
else
{
dp[k][m]++;
vector <int> c; // this array stores the candidates for postion k.
// for (int kj : a) cout << kj << " ";
// cout << endl;
if (k == a.size() ) // if (is_a_soln) process_solution
{
if (m < money)
{
b = true;
money = m;
garr = a;
}
}
else // else backtrack with updated parameters
{
// k++;
construct_candidates(a, k , m, c);
for (int i = 0; i < c.size(); i++)
{
a[k] = c[i];
backtrack(a, k, m - c[i]);
}
}
}
}