DP Review 1
这个dp啊,我就是直接用题目来说了
USACO3.1.2 总分
洛谷上面的链接
这一道题是一道比较容易看出来的题目,就是设f[n]
代表时间为n的时候的最大的分数,然后就枚举第几个种类以及时间就可以了(就是背包问题啊)
Code
#include<bits/stdc++.h>
#define maxn 10002
#define Int64 long long
using namespace std;
int M,N;//时间,种类
int t[maxn],s[maxn];//耗时,分数
Int64 f[maxn];
int main(){
scanf("%d%d",&M,&N);
for(int i=1;i<=N;i++){
scanf("%d%d",&s[i],&t[i]);
}
memset(f,0,sizeof(f));
for(int i=1;i<=N;i++){
for(int j=1;j<=M;j++){
if(j>=t[i]){
f[j]=max(f[j],f[j-t[i]]+s[i]);
}
}
}
cout<<f[M];
return 0;
}
逃亡的准备
Description
在《Harry Potter and the Deathly Hallows》中,Harry Potter他们一起逃亡,现在有许多的东西要放到赫敏的包里面,但是包的大小有限,所以我们只能够在里面放入非常重要的物品,现在给出该种物品的数量、体积、价值的数值,希望你能够算出怎样能使背包的价值最大的组合方式,并且输出这个数值,赫敏会非常地感谢你。
Input
第一行有2个整数,物品种数n和背包装载体积v。 第 2 行到 n+1 行每行3个整数,为第i种物品的数量m、体积w、价值s。.
Output
仅包含一个整数,即为能拿到的最大的物品价值总和。
Sample Input
2 10
3 4 3
2 2 5
Sample Output
13
Analysis
这一道题啊,一眼就可以看出是一个多重背包问题所以说就可以写出核心的代码
for(int i=1;i<=n;i++){
for(int j=v;j>=1;j--){
for(int k=1;k<=m[i];k++){
if(j>=c[i]*k){
f[j]=max(f[j],f[j-k*c[i]]+k*p[i]);
}
}
}
}
如果你把上面那一段交上去,毫无疑问,你就会TLE几个点
为了优化,中间你应该写成
if(j>=c[i]*k){
f[j]=max(f[j],f[j-k*c[i]]+k*p[i]);
}
else break;
因为既然都比C[i]*k
小了,接着k还要继续增大,这不是浪费时间吗,
那么我们就大胆而合理的AC了这道题
这样就可以完美地解决超时的问题了啦
最大约数和
Analysis
这一道题根据题意,你首先要知道1~N
和之间每一个数的约数的和,可以通过下面一个函数来解决
inline void div(int x){
for(int i=2;i<=sqrt(x);i++){
if(!(x%i)){
factor_sum[x]+=(i+x/i);
if(i==sqrt(x))factor_sum[x]-=i;
}
}
factor_sum[x]++;
}
//获取每一个数的约数和
然后呢,就需要dp了,这一个自己感觉是有点像是一个完全背包,但是这并不代表这是一个完全背包的题,我的意思是,在累加的过程中,你选择的累加的数是有无限多个,因此从前往后枚举就可以了
for(int i=1;i<=n;i++){
for(int j=1;j<=i;j++){
factor_sum[i]=max(factor_sum[i],factor_sum[j]+factor_sum[i-j]);
}
}
想到了这些,就可以AC了