\ (Acwing \) algorithm Advanced Learning \ (dp \) Topics: knapsack problem
Knapsack problem:
- Knapsack problem is linear \ (dp \) a very special kind of model.
- 01 Backpack: goods can only be used once.
- Full backpack: items can be used unlimited times.
- Multiple backpack: Each item has a number of limitations.
- Backpack group: Each group can only choose one of several groups.
Example. 1 acw278: digital combined
Meaning of the questions:
- Given \ (n \) numbers, to choose the number of digits and make them as \ (m \) , asked how many kinds of programs.
Ideas:
- 01 knapsack problem.
\ (a_i \) as a volume, \ (m \) as a backpack capacity, \ (F (J) \) on behalf and for the \ (J \) the number of programs.
Metastasis equation \ (F (J) = F + (JA (I)) \) .
#include<bits/stdc++.h>
using namespace std;
const int maxn = 1e2+10;
const int maxm = 1e4+10;
int a[maxn], n, m, f[maxn];
int main(){
cin >> n >> m;
for(int i = 1; i <= n; i++)
scanf("%d", &a[i]);
f[0] = 1;
for(int i = 1; i <= n; i++)
for(int j = m; j >= a[i]; j--)
f[j] += f[j-a[i]];
cout << f[m] << endl;
return 0;
}
Example 2 acw279: a natural number of split
The meaning of problems
- To a natural number \ (n-\) , requires the \ (n-\) split into several additive in the form of an integer, may participate in the digital operation repeated.
- Find a few programs.
Thinking
- Full backpack, because a number can be used many times.
#include<bits/stdc++.h>
using namespace std;
typedef long long ll;
const int maxn = 4e3+10;
const ll mod = 2147483648;
ll f[maxn], n;
int main()
{
cin >> n;
f[0] = 1;
for(int i = 1; i <= n-1; i++)
for(int j = i; j <= n; j++)
f[j] = (f[j]+f[j-i])%mod;
f[n] = (f[n]+mod)%mod;
cout << f[n] << endl;
return 0;
}
Example 3 acw280: jury
The meaning of problems
- There \ (n-\) individuals, each individual has two scores \ (P (I), D (I) \) , selected from the group \ (m \) who find that the program \ (| DP | \) minimum, multiple kind of legitimate program, then select \ (d + p \) the largest group.
data range
- \(n\leq 200,m\leq 20, p,d\leq 20\)
Thinking
- Elected very few people, but the score difference is low, so you can sort by the difference between the first program, which is \ (- 400 \) to \ (+ 400 \) scores section.
- Then we can go to a difference of \ (0 \) program to find, if not go to \ (1, -1 \) there is no such plan, ...
- Therefore, the definition of \ (f (i, j, k) \) represents the former \ (I \) individuals select \ (J \) individuals and difference of \ (K \) a \ (p + d \) maximum .
- For each person may only pick or ban, so this is a 01 backpack.
- Transfer equation \ (: f (i, j , k) = max \ {f (i-1, j, k), f (i, j-1, k- (p_i-d_i)) + (p_i + d_i) \} \) .
#include<bits/stdc++.h>
using namespace std;
const int maxn = 200 + 10;
const int maxm = 800 + 10;
const int base = 400;
int n, m;
int f[maxn][25][maxm];
int p[maxn], d[maxn];
int ans[maxn];
int main()
{
int cnt = 1;
while(scanf("%d%d", &n, &m))
{
if(n==0 && m==0) break;
for(int i = 1; i <= n; i++)
scanf("%d%d", &p[i], &d[i]);
memset(f, -0x3f, sizeof(f));
f[0][0][base] = 0;
for(int i = 1; i <= n; i++)
for(int j = 0; j <= m; j++)
for(int k = 0; k < maxm; k++)
{
f[i][j][k] = f[i-1][j][k];
int tmp = k-(p[i]-d[i]);
if(tmp < 0 || tmp >= maxm) continue;
if(j < 1) continue;
f[i][j][k] = max(f[i][j][k], f[i-1][j-1][tmp]+p[i]+d[i]);
}
int v = 0;
while(f[n][m][base-v] < 0 && f[n][m][base+v] < 0) v++;
if(f[n][m][base-v] > f[n][m][base+v]) v = base - v;
else v = base + v;
int i = n, j = m, k = v, tot = 0;
while(j)
{
if(f[i][j][k] == f[i-1][j][k])// 可以不选第i个人
i--;
else
{
ans[++tot] = i; //选第i个人
k -= (p[i]-d[i]);
i--, j--;
}
}
int ansp = 0, ansd = 0;
for(int i = 1; i <= tot; i++)
{
ansp += p[ans[i]];
ansd += d[ans[i]];
}
printf("Jury #%d\n", cnt++);
printf("Best jury has value %d for prosecution and value %d for defence:\n", ansp, ansd);
for (int i = 1; i <= tot; i ++ )
printf(" %d", ans[i]);
puts(""); puts("");
}
return 0;
}
Example 4 acw281: coins
The meaning of problems
- For \ (n-\) type of coin, the \ (I \) denominations as \ (a_i \) , an amount of \ (C_i \) a, Q from a plurality of coin selected, Q \ (1 \) to \ (m \ ) intervals can form themselves into the number of face value.
data range
- \(n\leq 100, m\leq10^5,a_i\leq10^5,c_i\leq10^3\)。
Thinking
- Multiple backpack should be no problem.
- Multiple backpack write directly is not, in fact, dangerous binary Optimized about getting bigger, monotone queue optimization would be able to control \ (10 ^ 7 \) calculation.
- But here is the thing to note:
- This problem is only concerned about the "feasibility" does not concern "optimality."
- That is, we are only concerned if he can scrape up.
- Set \ (f (i, j) \) represents the previous \ (I \) th items, a nominal value of \ (J \) if it can be put together.
- For the first \ (i \) type of coin could add up to \ (j \) are only two possible face value.
- Minato has been good.
- \ (ja (i) \) Minato Well, then \ (j \) from \ (ja (i) \) transfer over.
- Set \ (vis (j) \) represents the first \ (i \) when a state, make up \ (j \) how to use a face value of at least \ (i \) coins.
- So when the transfer is to scrape out as much as possible with the previous state, so that the first \ (i \) type of coins can achieve "at least" such a possibility.
- That is to say, for the first \ (i \) states that if his \ (J == to true \) , then you can not have the first \ (i \) kinds of coins.
- If for \ (j \) instead of \ (to true \) , but \ (f (ja (i) ) == true \) and when there are enough coins, you can transfer.
- Refer to code.
#include<bits/stdc++.h>
using namespace std;
const int maxn = 1e2 + 10;
const int maxm = 1e5 + 10;
bool f[maxm];
int n, m;
int a[maxn], c[maxn];
int vis[maxm];
int main()
{
while(cin >> n >> m)
{
if(n == 0 && m == 0) break;
memset(f, 0, sizeof(f));
f[0] = true;
for(int i = 1; i <= n; i++) scanf("%d", &a[i]);
for(int i = 1; i <= n; i++) scanf("%d", &c[i]);
for(int i = 1; i <= n; i++)
{
for(int j = 0; j <= m; j++) vis[j] = 0;
for(int j = a[i]; j <= m; j++)
if(!f[j] && f[j-a[i]] && vis[j-a[i]] < c[i]) {
f[j] = true;
vis[j] = vis[j-a[i]]+1;
}
} int ans = 0;
for(int i = 1; i <= m; i++)
ans += f[i];
cout << ans << endl;
}
return 0;
}