DP Review 1

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

原文地址:https://www.cnblogs.com/perisino/p/10405796.html