知识总结
个人对动态规划的理解并不深刻,只知道是通过某种计算顺序,实现对最优化问题的求解。
题解
A - 送快弟
现在我们有N个配件,他们有不同的价值. 但是我们背包的容量是有限的,因为我们只有一个一级包, 所以我们最多可以装V重量的东西. 但是为了能更好的吃到鸡(不存在的)我们要携带更有价值的配件,请问我们最多能拿多少价值的配件来当快递员呢??
Input
输入的第一行是T, 表示有一共要打T场比赛.
每组数据由三行组成.
第一行包含两个整数N和V(N <= 1000, V <= 1000). N表示配件的个数, V表示一级包的大小(系统会更新嘛).
第二行包含N个整数, 表示每一个配件的价值.
第三行包含N个整数, 表示每个配件的重量.
Output
对每一组数据, 输出我们最多能拿多少价值的配件.
Sample Input
1
10 10
1 3 5 7 9 11 13 15 17 19
19 17 15 13 11 9 7 5 3 1
Sample Output
51
解题思路
01背包问题板子题,直接套板解决
题解
#include<iostream>
#include<algorithm>
#include<cstring>
using namespace std;
const int N = 1010;
int n, m;
int v[N], w[N];
int f[N][N];
int main()
{
int t;
scanf("%d", &t);
while(t--)
{
scanf("%d%d", &n, &m);
memset(f, 0, sizeof f);
for(int i=1; i<=n; ++i)
scanf("%d", &w[i]);
for(int i=1; i<=n; ++i)
scanf("%d", &v[i]);
for(int i=1; i<=n; ++i)
{
for(int j=0; j<=m; ++j)
{
f[i][j] = f[i-1][j];
if(j>=v[i])
f[i][j] = max(f[i][j], f[i-1][j-v[i]]+w[i]);
}
}
printf("%d\n", f[n][m]);
}
return 0;
}
B - CD
You have a long drive by car ahead. You have a tape recorder, but unfortunately your best music is on CDs. You need to have it on tapes so the problem to solve is: you have a tape N minutes long. How to choose tracks from CD to get most out of tape space and have as short unused space as possible.
Assumptions:
number of tracks on the CD. does not exceed 20
no track is longer than N minutes
tracks do not repeat
length of each track is expressed as an integer number
N is also integer
Program should find the set of tracks which fills the tape best and print it in the same sequence as the tracks are stored on the CD
Input
Any number of lines. Each one contains value N, (after space) number of tracks M and durations of the tracks. For example from first line in sample data: N=5, M=3, first track lasts for 1 minute, second one 3 minutes, next one 4 minutes
The input data satisfies the following constraints:
N≤10000
M≤20
Output
Set of tracks (and durations) which are the correct solutions and string ``sum:" and sum of duration times.
Sample Input
5 3 1 3 4
10 4 9 8 4 2
20 4 10 5 7 4
90 8 10 23 1 2 3 4 5 7
45 8 4 10 44 43 12 9 8 2
Sample Output
1 4 sum:5
8 2 sum:10
10 5 4 sum:19
10 23 1 2 3 4 5 7 sum:55
4 10 12 9 8 2 sum:45
解题思路
01背包求方案板子题,逆序dp,正序枚举输出方案。
代码
#include<iostream>
#include<algorithm>
#include<cstring>
using namespace std;
const int N = 22, M = 10010;
int n, m;
int v[N], w[N];
int f[N][M];
int main()
{
while(~scanf("%d%d", &m, &n))
{
memset(f, 0, sizeof f);
for(int i=1; i<=n; ++i)
{
scanf("%d", &v[i]);
w[i] = v[i];
}
for(int i=n; i>=1; --i)
{
for(int j=0; j<=m; ++j)
{
f[i][j] = f[i+1][j];
if(j>=v[i])
f[i][j] = max(f[i][j], f[i+1][j-v[i]]+w[i]);
}
}
int j = m;
for(int i=1; i<=n; ++i)
{
if(f[i][j] == f[i+1][j-v[i]]+w[i])
{
printf("%d ", v[i]);
j-=v[i];
}
}
printf("sum:%d\n", f[1][m]);
}
return 0;
}